我正在学习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
构造会失败,并出现异常。