Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.04.2017, 08:26   #1
ivan.tiran
Форумчанин
 
Аватар для ivan.tiran
 
Регистрация: 24.08.2011
Сообщений: 138
По умолчанию Как сделать, чтобы числа в нормальном законе распределения были каждый раз разные?

Доброго времени суток. В своей работе моделирую измерения. Для этого вычисляю погрешности с помощью функции:
Код:
std::normal_distribution
Погрешности моделируются замечательно. Но, мне не нравится, что с каждым запуском программы они всегда одинаковые.

Помнится, что в rand() я использовал:
Код:
srand(time(NULL))
для этого, но для std::normal_distribution это не работает.

Как посчитать погрешности по нормальному закону распределения, чтобы они при каждом запуске программы были каждый раз разными?
ivan.tiran вне форума Ответить с цитированием
Старый 21.04.2017, 08:38   #2
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Код:
std::random_device rd;
std::mt19937 gen(rd());

std::normal_distribution<> d(5,2);
d(gen);
p51x на форуме Ответить с цитированием
Старый 21.04.2017, 08:55   #3
ivan.tiran
Форумчанин
 
Аватар для ivan.tiran
 
Регистрация: 24.08.2011
Сообщений: 138
По умолчанию

Цитата:
Сообщение от p51x Посмотреть сообщение
Код:
std::random_device rd;
std::mt19937 gen(rd());

std::normal_distribution<> d(5,2);
d(gen);
Всё равно одинаковые(((
ivan.tiran вне форума Ответить с цитированием
Старый 21.04.2017, 09:26   #4
ivan.tiran
Форумчанин
 
Аватар для ivan.tiran
 
Регистрация: 24.08.2011
Сообщений: 138
По умолчанию

Вот, мой код. Может, я что-то неправильно делаю?

Код:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <QVector>
#include "consts.h"
#include <random>
#include <time.h>


struct NU
{

    double x,y,vx,vy;

};


void runge_kut(double xx,double yy,double vxx,double vyy, double Step, double * b);
void CentralBody(double *r, double *w_gpz);
QVector<double> calcDeltaD(int begin, int end);
QVector<double> calcDeltaDp(int begin, int end);
QVector<double> calcD(QVector<NU> nu,QVector<double> deltaD);
QVector<double> calcDp(QVector<NU> nu,QVector<double> deltaDp,QVector<double> D);



int main()
{

    double x0 = 0.0;
    double y0 = 6671.0;
    double Vx0 = 7.72989;
    double Vy0 = 0.0;
    int Step = 1;
    int timeBegin = 0;
    int iterationTimeSec = 600;
    double b[4];
    QVector<double> deltaD,deltaDp;
    QVector<double> D,Dp;

    QVector<NU> nu;

    NU a;

    a.x = x0;
    a.y = y0;
    a.vx = Vx0;
    a.vy = Vy0;

    nu.append(a);


    for(int i = timeBegin + Step;i<iterationTimeSec;i+=Step)
    {
        runge_kut(x0,y0,Vx0,Vy0, Step, b);

        NU a;

        a.x  =  b[0];
        a.y  =  b[1];
        a.vx = b[2];
        a.vy = b[3];

        nu.append(a);

        x0 = a.x;
        y0 = a.y;
        Vx0= a.vx;
        Vy0= a.vy;
    }




    deltaD = calcDeltaD(timeBegin,iterationTimeSec);
    deltaDp = calcDeltaDp(timeBegin,iterationTimeSec);

    D = calcD(nu,deltaD);
    Dp = calcDp(nu,deltaDp,D);



    for(int i=0;i<nu.count();i++)
    {
        printf("%i\tD = %f\tDp = %f\n",i+1,deltaD[i],deltaDp[i]);

    }




    nu.clear();
    deltaD.clear();
    deltaDp.clear();
    return 0;
}


void runge_kut(double xx,double yy,double vxx,double vyy, double Step, double * b)
{


    double k1[2],k2[2],k3[2],k4[2];
    double m1[2],m2[2],m3[2],m4[2];
    double w_gpz_GSK[2] = {0,0};
    double f_GSK[2] = {0,0};
    double r_GSK[2] = {0,0};
    double v_GSK[2] = {0,0};
    double r0_GSK[2] = {0,0};
    double v0_GSK[2] = {0,0};


    for (int i =0; i < 2; i++)
    {
        k1[i] = 0; k2[i] = 0; k3[i] = 0; k4[i] = 0;
        m1[i] = 0; m2[i] = 0; m3[i] = 0; m4[i] = 0;
    }


    r_GSK[0] = xx;
    r_GSK[1] = yy;

    v_GSK[0] = vxx;
    v_GSK[1] = vyy;


    r0_GSK[0] = r_GSK[0];
    r0_GSK[1] = r_GSK[1];
    v0_GSK[0] = v_GSK[0];
    v0_GSK[1] = v_GSK[1];


    CentralBody(r_GSK,w_gpz_GSK);


    f_GSK[0] = w_gpz_GSK[0] * r_GSK[0];
    f_GSK[1] = w_gpz_GSK[1] * r_GSK[1];



    for (int i = 0; i < 2; i++)
    {
        k1[i] = Step*v_GSK[i];
        m1[i] = Step*f_GSK[i];
        r_GSK[i] =r0_GSK[i] + k1[i]/2.;
        v_GSK[i] =v0_GSK[i] + m1[i]/2.;
    }




    CentralBody(r_GSK,w_gpz_GSK);
    f_GSK[0] = w_gpz_GSK[0] * r_GSK[0];
    f_GSK[1] = w_gpz_GSK[1] * r_GSK[1];


    for (int i = 0; i < 2; i++)
    {
        k2[i] = Step*v_GSK[i];
        m2[i] = Step*f_GSK[i];
        r_GSK[i] =r0_GSK[i] + k2[i]/2.;
        v_GSK[i] =v0_GSK[i] + m2[i]/2.;
    }




    CentralBody(r_GSK,w_gpz_GSK);

    f_GSK[0] = w_gpz_GSK[0] * r_GSK[0];
    f_GSK[1] = w_gpz_GSK[1] * r_GSK[1];


    for (int i = 0; i < 2; i++)
    {
        k3[i] = Step*v_GSK[i];
        m3[i] = Step*f_GSK[i];
        r_GSK[i] =r0_GSK[i] + k3[i];
        v_GSK[i] =v0_GSK[i] + m3[i];
    }


    CentralBody(r_GSK,w_gpz_GSK);

    f_GSK[0] = w_gpz_GSK[0] * r_GSK[0];
    f_GSK[1] = w_gpz_GSK[1] * r_GSK[1];


    for (int i = 0; i < 2; i++)
    {
        k4[i] = Step*v_GSK[i];
        m4[i] = Step*f_GSK[i];

        b[i] =r0_GSK[i] + 1/6.*(k1[i]+2*k2[i]+2*k3[i]+k4[i]);
        b[i+2] =v0_GSK[i] + 1/6.*(m1[i]+2*m2[i]+2*m3[i]+m4[i]);
    }
}


void CentralBody(double *r, double *w_gpz)
{
    double mod_r = sqrt(r[0]*r[0] + r[1]*r[1]);
    for (int i = 0; i < 2; i++)
    {
        w_gpz[i] = -MU/(mod_r*mod_r*mod_r);
    }
}



QVector<double> calcDeltaD(int begin, int end)
{
    QVector<double> ret;


    std::random_device rd;
    std::mt19937 engine(rd());
    std::normal_distribution<double> dist(0.0,sigmaD);


    for(int i = begin;i<end;i++)
    {
        double  delta_d = dist(engine);
        ret.append(delta_d);
    }
    return ret;
}


QVector<double> calcDeltaDp(int begin, int end)
{
    QVector<double> ret;

    std::random_device rd;
    std::mt19937 engine(rd());
    std::normal_distribution<double> dist(0.0,sigmaDp);


    for(int i = begin;i<end;i++)
    {
        double  delta_dp = dist(engine);
        ret.append(delta_dp);
    }
    return ret;
}

QVector<double> calcD(QVector<NU> nu,QVector<double> deltaD)
{
    QVector<double> D;

    for(int i=0;i<nu.count();i++)
    {
        double xMinxN = nu[i].x - xN;
        double yMinyN = nu[i].y - yN;
        double d = sqrt(xMinxN*xMinxN + yMinyN*yMinyN) + deltaD[i];
        D.append(d);
    }


    return D;
}

QVector<double> calcDp(QVector<NU> nu,QVector<double> deltaDp,QVector<double> D)
{
    QVector<double> Dp;

    for(int i=0;i<nu.count();i++)
    {
        double xMinxN = nu[i].x - xN;
        double yMinyN = nu[i].y - yN;

        double dp = ( xMinxN*nu[i].vx +  yMinyN*nu[i].vy) / (D[i]) + deltaDp[i];
        Dp.append(dp);
    }


    return Dp;
}
Вложения
Тип файла: 7z kalman.7z (1.7 Кб, 6 просмотров)
ivan.tiran вне форума Ответить с цитированием
Старый 21.04.2017, 15:20   #5
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
static std::mt19937 engine(std::chrono::system_clock::n ow().time_since_epoch().count());
std::normal_distribution<double> dist(0.0,sigmaD);
Смысл в том, что engine должна жить от начала до конца работы и получать seed только в начале от времени. От другого генератора смысла нет, т.к. тот генератор тоже выдает одинаковые числа. Хотя, можно взять энтропийный генератор, вместо времени (который аппаратно случаен, но много чисел он не даст)

Последний раз редактировалось alexzk; 21.04.2017 в 15:24.
alexzk вне форума Ответить с цитированием
Старый 21.04.2017, 20:55   #6
ivan.tiran
Форумчанин
 
Аватар для ivan.tiran
 
Регистрация: 24.08.2011
Сообщений: 138
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Смысл в том, что engine должна жить от начала до конца работы и получать seed только в начале от времени. От другого генератора смысла нет, т.к. тот генератор тоже выдает одинаковые числа. Хотя, можно взять энтропийный генератор, вместо времени (который аппаратно случаен, но много чисел он не даст)
Я просто в шоке. Пришёл домой. Решил проверить, как моделируются погрешности пока без этого кода. Дома в качестве ОС использую Ubuntu. И что вы думаете?
Числа - разные. Почему так?
На XP - одинаковые, на Ubuntu - разные? Мистика.
ivan.tiran вне форума Ответить с цитированием
Старый 21.04.2017, 21:13   #7
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Цитата:
На XP - одинаковые, на Ubuntu - разные? Мистика.
Никапли. В линукса зачастую испульзую /dev/(u)rand для генерации в отличии от винды ХП.
p51x на форуме Ответить с цитированием
Старый 21.04.2017, 21:17   #8
ivan.tiran
Форумчанин
 
Аватар для ivan.tiran
 
Регистрация: 24.08.2011
Сообщений: 138
По умолчанию

Цитата:
Сообщение от p51x Посмотреть сообщение
Никапли. В линукса зачастую испульзую /dev/(u)rand для генерации в отличии от винды ХП.
Неочень понял. Это особенность пингвинов такая генерить разный рандом?
ivan.tiran вне форума Ответить с цитированием
Старый 21.04.2017, 23:44   #9
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от ivan.tiran Посмотреть сообщение
Неочень понял. Это особенность пингвинов такая генерить разный рандом?
Нет, он имел ввиду, что в линуксах есть "аппаратный" генератор энтропии и он используется по умолчанию - там накапливается случайность, от движения мыши и т.д. Но, такая штука ограничена, если ничего не делать (не трогать мышь и т.д.) - числа быстро иссякнут и будут задержки генерации. Обычно его для криптографий берегут.

Т.о. в вашем примере, для старта второго генератора используется первый, который на линуксе аппаратный автоматически. Добавьте там static все равно, иначе при каждом вызове ф. будет перезапуск цепи.

Последний раз редактировалось alexzk; 21.04.2017 в 23:47.
alexzk вне форума Ответить с цитированием
Старый 22.04.2017, 11:40   #10
ivan.tiran
Форумчанин
 
Аватар для ivan.tiran
 
Регистрация: 24.08.2011
Сообщений: 138
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Нет, он имел ввиду, что в линуксах есть "аппаратный" генератор энтропии и он используется по умолчанию - там накапливается случайность, от движения мыши и т.д. Но, такая штука ограничена, если ничего не делать (не трогать мышь и т.д.) - числа быстро иссякнут и будут задержки генерации. Обычно его для криптографий берегут.

Т.о. в вашем примере, для старта второго генератора используется первый, который на линуксе аппаратный автоматически. Добавьте там static все равно, иначе при каждом вызове ф. будет перезапуск цепи.
где статик прописать?
ivan.tiran вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как сделать, чтобы разные таблицы имели одинаковую ширину столбцов? Natalie_M Microsoft Office Word 7 02.05.2018 10:49
как сделать, чтобы текст, логотипы были привязаны к фону сайта? nikytt HTML и CSS 1 15.12.2015 00:35
Как сделать, чтобы с программой могли работать разные пользователи? вася радугов Помощь студентам 28 30.03.2014 23:28
Как сделать так, чтобы в Debug и Release использовались разные ддл'ки? TwiX Visual C++ 7 08.11.2011 10:51
Как сделать чтобы новые строки всегда были в области видимости? neugadal Microsoft Office Excel 9 06.09.2008 12:23