为什么uniform_int_distribution适用于 62 位数字,但不适用于 63 或 64 位数字?
我很难理解为什么此代码(尝试在 C++11 中使用新的
标头)在 [0, 2**62 中正确生成随机数- 1]
,但不是 [0, 2**63 - 1]
或 [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;
}
现在,进一步挖掘发现 std::mt19937_64
,它具有正确的行为,但是任何人都可以向我解释为什么适用于 62 位数字的东西不适用于 64 位数字吗?
编辑:抱歉,我什至没有具体说明问题。 问题是,对于 63 和 64 位最大值,输出始终是 [0, 2**32 - 1]
范围内的数字,例如:
% ./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
编辑2:我正在使用clang++
(Apple clang version 2.1 (tags/Apple/clang-163.7.1)
)和“libc++”。我无法使用 GCC 轻松测试上述内容,因为我的版本没有 c++0x
支持。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您发现了 libc++ 中的一个错误。谢谢!!!
我已对tip-of-trunk 修订版143104 提交了以下修复:
此修复不需要重新编译二进制libc++.dylib。
You've found a bug in libc++. Thanks!!!
I have committed the following fix to tip-of-trunk revision 143104:
This fix does not require a recompile of the binary libc++.dylib.
由于 std::mt19937 是 32 位版本,因此最有可能发生的情况是,在生成下一个数字时,它会假设哪些位在其“工作空间”中重要和不重要。当生成可能包含最后两位的数字时,这会导致溢出。我怀疑您会发现实际分布并不均匀,32 位引擎上的最大数量高于
2**32 - 1
。Since
std::mt19937
is the 32-bit version, most likely what's happening is it's making assumptions about which bits do and do not matter in its "work space" when generating the next number. This then results in overflow when generating numbers that could including those last two bits. I suspect that you'd find the actual distribution is not really uniform with max numbers higher than2**32 - 1
on the 32 bit engine.