I'm generating some seeded random numbers in D using the default random number generation engine, and I'm getting some "slightly off" values depending on whether I request integer or floating point/double random number generation. For example this code:
import std.random; // From docs: alias Random = MersenneTwisterEngine!(uint, 32, 624, 397, 31, 2567483615u, 11, 7, 2636928640u, 15, 4022730752u, 18).MersenneTwisterEngine;
int seed = 123;
Random genint = Random(seed);
Random gendouble = Random(seed);
foreach (i; 0..4) {
writefln("rand[%d]: %d %f", i, uniform(0, 1000000, genint), uniform(0.0, 1000000.0, gendouble));
}
generates these results:
rand[0]: 696626 696469.187433
rand[1]: 713115 712955.321584
rand[2]: 286203 286139.338810
rand[3]: 428567 428470.925062
For some reason they're close but off by a noticeable amount. Is this expected behavior? I'm not completely familiar with the method being used to generate the numbers so I'm wondering what might be causing this to occur. Specifically, the reason I'm curious about this is I'm trying to port some D code to Objective-C, using the MTRandom library:
int seed = 123;
MTRandom *genint = [[MTRandom alloc] initWithSeed:seed];
MTRandom *gendouble = [[MTRandom alloc] initWithSeed:seed];
for (int i = 0; i < 4; i++) {
NSLog(@"rand[%d]: %d %f", i, [genint randomUInt32From:0 to:1000000], [gendouble randomDoubleFrom:0.0 to:1000000.0]);
}
and I'm getting these results:
rand[0]: 696469 696469.187433
rand[1]: 712956 712955.321584
rand[2]: 286139 286139.338810
rand[3]: 428471 428470.925062
Identical for retrieving random doubles, but here the integer results are much closer.. though sometimes off by one! Is 712955.32 supposed to be rounded up to 712956 using this method of random generation? I just don't know...
What's the best way I can ensure that my seeded random integer generation is identical between D and Objective-C?
The following is based on a very quick review of the docs page:
I don't see where it's indicated that the results of uniform!int
and uniform!double
should even be remotely close, nor any specification on how the bits from the random number generator get converted to the requested type.
In short, I think the int
s and double
s being close is an implementation detail and you can not depend on it. Furthermore, I'd not depend on the obj-c and D implementations returning the same sequence of double
s, even from the same seed. (I expect you can count of the MT construct producing the same bit stream however.)
If you need the same sequence, then you will need to crack open the obj-c version and port it to D as well.