我正在学习C ++,并且在我的随机数gen代码中,我总是得到相同的数字

random_device rd;
mt19937 x{rd()};
uniform_int_distribution<int> ran{1, 100};
cout << ran(x);


但是srand / rand()起作用。

srand (time(0));
cout << rand()%100;


我认为这与time()有关。但是如何获得第一个有效的代码?

最佳答案

假设您的问题出在MinGW g ++编译器上,则可以定义一个包装<random>的标头,如下所示:

#pragma once

#ifndef MY_NO_FIX_OF_RANDOM_DEVICE
#   ifdef __GNUC__
#       undef   _GLIBCXX_USE_RANDOM_TR1
#       define  _GLIBCXX_USE_RANDOM_TR1
#   endif
#endif
#include <random>


那只是a header in the Wrapped stdlib library的SO修改版本。

我建议使用此修补程序的强制包含(命令行选项),或仅在命令行中定义_GLIBCXX_USE_RANDOM_TR1



通过检查我的MinGW g ++ 7.3.0的源代码,文件<random.h>random.cc,看来该方法适用于大多数PC,因为(使用该编译器)_GLIBCXX_USE_RANDOM_TR1通过rdrand指令选择数字生成, (如果有),或者通过"/dev/urandom" * nix world设备(如果有)。

因此,“有效”的标准是:


处理器支持rdrand指令,或者
fopen成功打开"/dev/urandom"


根据Wikipedia article about rdrand


  ” AMD在2015年6月增加了对该指令的支持。


...因此,此方法可能在之前装有AMD处理器(没有"/dev/urandom"指令)的Windows PC(没有rdrand)上失败。



技术细节:

使用_GLIBCXX_USE_RANDOM_TR1定义的random_device默认构造函数使用参数"default"调用以下函数:

  void
  random_device::_M_init(const std::string& token)
  {
    const char *fname = token.c_str();

    if (token == "default")
      {
#if (defined __i386__ || defined __x86_64__) && defined _GLIBCXX_X86_RDRAND
    unsigned int eax, ebx, ecx, edx;
    // Check availability of cpuid and, for now at least, also the
    // CPU signature for Intel's
    if (__get_cpuid_max(0, &ebx) > 0 && ebx == signature_INTEL_ebx)
      {
        __cpuid(1, eax, ebx, ecx, edx);
        if (ecx & bit_RDRND)
          {
        _M_file = nullptr;
        return;
          }
      }
#endif

    fname = "/dev/urandom";
      }
    else if (token != "/dev/urandom" && token != "/dev/random")
    fail:
      std::__throw_runtime_error(__N("random_device::"
                     "random_device(const std::string&)"));

    _M_file = static_cast<void*>(std::fopen(fname, "rb"));
    if (!_M_file)
      goto fail;
  }


如果__cpuid报告处理器支持rdrand指令,则这将导致_M_file成员被清零,这又将导致编号生成代码使用rdrand指令。

否则,此代码将尝试打开* nix随机设备,如果失败,则它将打开,因此random_device构造会失败,并出现异常。

07-25 22:28