20

C++ 11 で新しいヘッダーを使用しようとするこのコードが、orではなく<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

4

2 に答える 2

0

は32ビットバージョンであるためstd::mt19937、おそらく何が起こっているのかは、次の数値を生成するときに、その「ワークスペース」でどのビットが重要であり、重要ではないかについての仮定を行っていることです。これにより、最後の2ビットを含む可能性のある数値を生成するときにオーバーフローが発生します。2**32 - 1実際の分布は、32ビットエンジンよりも最大数が多いため、実際には均一ではないことがわかると思います。

于 2011-10-27T15:14:11.803 に答える