[Bug libstdc++/65723] uniform_real_distribution isn't uniform.
art at blahonga dot org
gcc-bugzilla@gcc.gnu.org
Fri Apr 10 09:36:00 GMT 2015
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65723
--- Comment #6 from art at blahonga dot org ---
(In reply to Jonathan Wakely from comment #1)
> I think this is WONTFIX. If you use from=0, to=2 then it works fine, so use
> those as the distribution parameters and then add 0x1p52 to the result.
It doesn't work fine. For any range. the 0x1p52 isn't the problem here.
new test hack.
#include <random>
#include <iostream>
#include <stdio.h>
#include <assert.h>
int
main(int argc, char **argv)
{
std::default_random_engine gen;
double from, step, to;
int range = 3;
switch (argc) {
case 1:
from = 1.0;
break;
default:
case 3:
range = atoi(argv[2]);
case 2:
from = atof(argv[1]);
break;
}
/*
* Calculate the nearest representable number after from.
* add 1.0 to deal with from being 0 (shouldn't cause overflow
* because at that range 1.0 means nothing).
*/
step = nextafter(from, (from + 1.0) * 2.0) - from;
/*
* uniform_real_distribution should return [from,to), but they
* all return [from,to], so that's why 1 is subtracted from range.
*/
to = from + step * (range - 1);
printf("%e %e %e %d\n", from, to, step, range);
std::uniform_real_distribution<double> dis(from, to);
int bucket[range];
int i;
for (i = 0; i < range; i++) {
bucket[i] = 0;
}
for (i = 0; i < 100 * range; i++) {
double r = dis(gen);
unsigned int b = (int)((r - from)/step);
if (b >= range) {
printf("foo: %d %f\n", b, r);
}
assert(b < range);
bucket[b]++;
}
for (i = 0; i < range; i++) {
printf("%d\n", bucket[i]);
}
return 0;
}
$ c++ -std=c++11 -o foo urd.cxx && ./foo
1.000000e+00 1.000000e+00 2.220446e-16 3
77
154
69
$ c++ -std=c++11 -o foo urd.cxx && ./foo 1.0 10000 | head -5
1.000000e+00 1.000000e+00 2.220446e-16 10000
46
107
119
102
$ c++ -std=c++11 -o foo urd.cxx && ./foo 0.0 100000 | head -5
0.000000e+00 4.940607e-319 4.940656e-324 100000
49
105
97
84
$ c++ -std=c++11 -o foo urd.cxx && ./foo 1000.5 555 | head -5
1.000500e+03 1.000500e+03 1.136868e-13 555
57
98
120
97
More information about the Gcc-bugs
mailing list