Почему 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 версии 2.1 (теги / Apple / clang-163.7.1) ) и «libc ++». Я не могу легко проверить это с помощью GCC, поскольку моя версия не поддерживает c ++ 0x .

20
задан bames53 3 November 2011 в 21:09
поделиться