I'm having difficulty understanding why this code, an attempt to use the new <random>
header in C++11, is correctly generating random numbers in [0, 2**62 - 1]
but not [0, 2**63 - 1]
or [0, 2**64 - 1]
.
#include <iostream>
#include <stdint.h>
#include <random>
#include <functional>
#include <ctime>
static std::mt19937 engine; // Mersenne twister MT19937
void print_n_random_bits (unsigned int n);
int main (void) {
engine.seed(time(0));
print_n_random_bits(64);
print_n_random_bits(63);
print_n_random_bits(62);
return 0;
}
void print_n_random_bits (unsigned int n)
{
uintmax_t max;
if (n == 8 * sizeof(uintmax_t)) {
max = 0;
} else {
max = 1;
max <<= n;
}
--max;
std::uniform_int_distribution<uintmax_t> distribution(0, max);
std::cout << n << " bits, max: " << max << std::endl;
std::cout << distribution(engine) << std::endl;
}
Now, a bit more digging reveals std::mt19937_64
, which has the correct behaviour, but can anyone explain to me why something that works for a 62 bit number doesn't work for a 64 bit one?
Edit: Sorry, I didn't even specify the problem. The problem is that for 63 and 64 bit max values, the output is consistently a number in the range [0, 2**32 - 1]
, e.g.:
% ./rand
64 bits, max: 18446744073709551615
1803260654
63 bits, max: 9223372036854775807
3178301365
62 bits, max: 4611686018427387903
2943926730538475327
% ./rand
64 bits, max: 18446744073709551615
1525658116
63 bits, max: 9223372036854775807
2093351390
62 bits, max: 4611686018427387903
1513326512211312260
% ./rand
64 bits, max: 18446744073709551615
884934896
63 bits, max: 9223372036854775807
683284805
62 bits, max: 4611686018427387903
2333288494897435595
Edit 2: I'm using clang++
(Apple clang version 2.1 (tags/Apple/clang-163.7.1)
) and "libc++". I can't easily test the above with GCC as my version doesn't have c++0x
support.
You've found a bug in libc++. Thanks!!!
I have committed the following fix to tip-of-trunk revision 143104:
Index: include/algorithm
===================================================================
--- include/algorithm (revision 143102)
+++ include/algorithm (working copy)
@@ -2548,7 +2548,7 @@
{
__u = __e_() - _Engine::min();
} while (__u >= __y0_);
- if (__w0_ < _EDt)
+ if (__w0_ < _WDt)
_S <<= __w0_;
else
_S = 0;
@@ -2561,7 +2561,7 @@
{
__u = __e_() - _Engine::min();
} while (__u >= __y1_);
- if (__w0_ < _EDt - 1)
+ if (__w0_ < _WDt - 1)
_S <<= __w0_ + 1;
else
_S = 0;
This fix does not require a recompile of the binary libc++.dylib.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With