我正在学习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()有关。但是如何获得第一个有效的代码?
答案 0 :(得分: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>
那只是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
成员被清零,这反过来又导致数字生成代码使用{{1} }指令。
否则,此代码将尝试打开* nix随机设备,如果该设备失败,则它将打开,因此rdrand
构造会失败,并出现异常。