简体   繁体   中英

Random Number Generation : same C++ code, two different behaviors

My colleague and I are working on a Monte Carlo project together, in C++. She uses Visual Studio, I use Xcode, we shared the code through git. We are computing American option prices thanks to a given method requiring random number generation. We realized we were getting wrong results for a certain parameter K (the higher the parameter, the more wrong the answer), and my colleague found that changing the random source for Mersenne Twister to rand() (though poor generator) made the results good for the whole range of K.

But when I changed the source on my version of the code, it did nothing.

More puzzling for me, I created a new Xcode project, copied inside it her whole source and it still gives me wrong results (while she gets good ones). So it can't stem from the code itself. I cleaned the project, relaunched Xcode, even restarted my computer (...), but nothing changes : our projects behaves consistently but differently, with the same code behind. (EDIT: by differently but consistently, I don't mean that we don't have the same sequence of numbers. I mean that her Monte Carlo estimator converges toward 4. and mine towards 3.)

Do you have any idea of what the cause of this dual behavior could be ?

Here is the random generation code :

double loiuniforme() //uniform law
{
    return (double)((float)rand() / (float)RAND_MAX);
}


vector<double> loinormale() //normal law
{
    vector<double> loinormales(2, 0.);

    double u1 = loiuniforme();
    double v1 = loiuniforme();

    loinormales[0] = sqrt(-2 * log(u1))*cos(2 * M_PI*v1);
    loinormales[1] = sqrt(-2 * log(u1))*sin(2 * M_PI*v1);

    return(loinormales);

}

EDIT : the MT RNG used before was :

double loiuniforme()
{
    mt19937::result_type seed = clock();
    auto real_rand = std::bind(std::uniform_real_distribution<double>(0,1), mt19937(seed));
    return real_rand();
}

The C++ standard does not specify what algorithm is used by rand() . Whoever wrote the compiler is free to use whatever implementation they want, and there is no guarantee that it will behave the same on two different compilers, on two different architectures or even two different versions of the same compiler.

You should only create one generator and use that for every number.

mt19937::result_type seed = clock();

and

mt19937(seed)

create a new generator, with a new seed, every time you call the function.
This causes the randomness to get all twisted.

You can use static variables in the function, since these are initialised on the first call:

double loiuniforme() 
{ 
    static std::mt19937 generator(clock()); 
    static std::uniform_real_distribution<double> distribution(0, 1); 
    return distribution(generator); 
}

(When you're comparing results with your colleague, use the same hardcoded seed to verify that you are getting the same results.)

You need to seed the rand function with the same number on both computers. And even then I'm not sure that the underlying code across computers and operating systems will return the same value.

More importantly, if you want identical results, don't use a random function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM