繁体   English   中英

为什么uniform_int_distribution <uintmax_t> 适用于62位数但不适用于63位或64位数?

[英]Why does uniform_int_distribution<uintmax_t> work for 62 bit numbers but not for 63 or 64 bit ones?

我很难理解为什么这个代码,尝试在C ++ 11中使用新的<random>标头,正确生成[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支持。

您在libc ++中发现了一个错误。 谢谢!!!

我已将以下修复程序提交给主干修订版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;

此修复程序不需要重新编译二进制libc ++。dylib。

由于std::mt19937是32位版本,所以最有可能的是它在生成下一个数字时假设哪些位在其“工作空间”中有效和无关紧要。 然后,当生成可包括最后两位的数字时,这会导致溢出。 我怀疑你发现32位引擎上的最大数字高于2**32 - 1 ,实际分布并不是真正均匀的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM