|
Boost : |
From: Damien Fisher (damien_at_[hidden])
Date: 2003-10-04 03:22:10
The following code demonstrates a bug in normal_distribution (in the
random library):
#include <boost/random/linear_congruential.hpp>
#include <boost/random/normal_distribution.hpp>
int main(void)
{
boost::minstd_rand generator(1);
boost::normal_distribution<boost::minstd_rand> r(generator);
r(); // Call r once, this will calculate two values (caching the second)
generator.seed(2);
std::cout << "First value: " << r() << std::endl;
std::cout << "First value (cache flushed): " << r() << std::endl;
generator.seed(2);
std::cout << "Second value: " << r() << std::endl;
r(); // Flush the cache
generator.seed(2);
std::cout << "Third value: " << r() << std::endl;
}
In my opinion, the first, third, and fourth values printed should be the
same. The output on my machine is:
First value: 5.95404e-05
First value (cache flushed): 0.610586
Second value: 0.000172468
Third value: 0.000172468
The reason for the first value being different is that the
normal_distribution generator calculates two values (using a Box-Muller
transform) and caches the second. When the seed is reset, it still
returns the cached value before generating values with the new seed.
This is clearly undesirable behavior: when changing the seed to a
specific value, the programmer expects, and sometimes requires, that the
values generated are always the same. I don't see any easy way of
fixing this, without some sort of mechanism for the normal_distribution
class to detect when the seed has changed.
Secondly, I noticed this page:
http://www.wikipedia.org/wiki/Box-Muller_transformation
According to the author of the page, the second variant of the transform
given is faster than the method currently used by normal_distribution.
I don't know whether this is true or not, but maybe it is worth
implementing.
Damien
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk