使用 TR1 /dev/random 生成C++中的随机数(可弹性运行 <1 秒)
generating random numbers in C++ using TR1 /dev/random (resilient to <1 second runs)
我想在c++中生成0到1之间的均匀随机数,以一种不使用标准rand()
和srand(time(NULL))
方法的方式。这样做的原因是,如果我在时钟的同一秒内多次运行应用程序,那么种子将完全相同并产生相同的输出。
我不想依赖于boost或OS/编译器的细节。可以假设为X86
似乎这样做的另一种方法是使用TR1(我没有c++ 11)并以某种方式播种/dev/random
?
现在我有这个,但它仍然使用time(NULL)
作为种子,在1秒内运行不正常:
#include <iostream>
#include <tr1/random>
int main()
{
std::tr1::mt19937 eng;
eng.seed(time(NULL));
std::tr1::uniform_int<int> unif(1, RAND_MAX);
int u = unif(eng);
std::cout << (float)u/RAND_MAX << std::endl;
}
应OP要求发布:
这仍然是特定于编译器的,但仍然可以在几乎所有针对x86的编译器上工作:
#ifdef _WIN32
// Windows
#define rdtsc __rdtsc
#else
// For everything else
unsigned long long rdtsc(){
unsigned int lo,hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return ((unsigned long long)hi << 32) | lo;
}
#endif
int main()
{
std::tr1::mt19937 eng;
eng.seed( rdtsc() ); // Seed with rdtsc.
std::tr1::uniform_int<int> unif(1, RAND_MAX);
int u = unif(eng);
std::cout << (float)u/RAND_MAX << std::endl;
}
这里的想法是用rdtsc
循环计数器作为随机数生成器的种子。
之所以有效是因为rdtsc
周期计数器迭代的速度与CPU频率差不多(通常相同)。因此,对它的两次调用返回相同值的可能性非常小-因此,使其成为RNG的优秀种子。
TR1 in [tr.rand.device]指定了一个random_device
类,它从一个依赖于实现的源生成无符号整数。所以下面的代码应该可以工作,尽管我没有自己编译:
int main() {
std::tr1::random_device dev_random;
std::tr1::mt19937 eng(dev_random());
...
在TR1中,直接传递dev_random而不调用它可以更随机地初始化eng的状态,但在c++ 11中,您必须将seed参数包装到另一个类中。由于调用参数在两个库中都可以工作,所以我将这样做是为了可维护性,除非您有更苛刻的需求。
您的问题与您播种随机数生成器的方式有关。显然,用时间(NULL)播种将在播种的那一秒内产生相同的PRNG序列。这是最常见的播种方式,但不幸的是,由于这个问题,这是不好的做法。不仅如此,我还读到它会导致结果的偏差。
注意如果使用相同的值,每个PRNG将产生相同的结果。所以你的问题与生成器无关,更多的是播种。
就在几周前,我在这里问了一个关于播种的问题,并给出了以下文章的链接,您可能也会发现这篇文章很有用。生物信息学应用中(伪)随机数生成的良好实践请参阅播种或预热生成器一节。
rand()不是最好的随机数生成器,但在许多情况下,只要它被适当地播种,它是合适的。如果你想要更好的东西,重复序列非常大,那么在那个链接中有一些提供。或者使用基于TR1的。就我个人而言,我会选择更可移植的基于c++ 03的代码,并避开TR1。
也考虑乘进作为一种替代的PRNG算法。
- 运行同一解决方案的另一个项目的项目
- CMake-按正确顺序将项目与C运行时对象文件链接
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- 代码在main()中运行,但在函数中出现错误
- 我在c++代码中生成了一个运行时#3异常
- 如何在linux终端中同时编译和运行c++代码
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 如何在运行中期切换GTK CSS style_context
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 如何在MS Visual Studio 2019中运行QT UI
- 如何通过cpp程序运行shell脚本
- 呼叫运营商<<临时
- IPC使用多个管道和分支进程来运行Python程序
- 删除指向指针的指针是运行时错误吗
- 如何用参数值调用函数(仅在运行时已知)
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- c++中的指针和运行时错误
- 在C应用程序中运行C++(带有STL)函数
- 运行程序时出现问题