C++ 14:2随机生成器 - 一个工作,另一个不工作

Ada*_*ato 0 c++ c++14

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

random_device rd;
mt19937 x{rd()};
uniform_int_distribution<int> ran{1, 100};
cout << ran(x);
Run Code Online (Sandbox Code Playgroud)

但是srand/rand()有效.

srand (time(0));
cout << rand()%100;
Run Code Online (Sandbox Code Playgroud)

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

Che*_*Alf 7

假设你的问题在于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>
Run Code Online (Sandbox Code Playgroud)

这只是Wrapped stdlib库中标题的修改版本.

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


通过检查我的MinGW的g ++ 7.3.0,文件的源代码<random.h>random.cc,看来,该方法适用于大多数PC,因为(与编译器)_GLIBCXX_USE_RANDOM_TR1通过选择数产生rdrand指令,如果有的话,和其他通过"/dev/urandom"*nix的世界设备,如果可供使用的话.

所以,"工作"的标准:

  • 处理器支持rdrand指令,
  • fopen成功开放"/dev/urandom".

根据维基百科的文章rdrand

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

...所以这种方法在Windows PC上可能会失败(没有"/dev/urandom")在此之前生成的AMD处理器(没有rdrand指令).


技术细节:

使用_GLIBCXX_USE_RANDOM_TR1defined,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;
  }
Run Code Online (Sandbox Code Playgroud)

如果__cpuid报告处理器支持该rdrand指令,那么这会导致_M_file成员归零,这反过来导致数字生成代码使用该rdrand指令.

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

  • 你能解释一下*为什么*有帮助吗?这是MinGW中的一个错误的解决方法吗?在`_GLIBCXX_USE_RANDOM_TR1`下定义了什么,为什么我们插入编译器特定的宏? (4认同)