RNG 函数 C++
Posted
技术标签:
【中文标题】RNG 函数 C++【英文标题】:RNG function C++ 【发布时间】:2019-06-03 23:01:11 【问题描述】:我正在尝试用 C++ 编写一个函数,该函数每次返回一个介于 0 和 1 之间的随机浮点/双精度值,每次都具有不同的值。
我尝试了几种不同的 srand、rand 和 RAND_MAX 方向,但每次运行代码时,每次都应该更改的某些值具有恒定值。我有一个术语,即 x = 20 * randomnumber() 但每次它都会为 x 返回相同的值。无论我多久运行一次代码。这是我的功能。
double randomnumber()
srand(time(NULL))
double r1 = ((double)rand()) / RAND_MAX);
return r1;
我想要它做的是生成一个介于 0 和 1 之间的浮点数,这样当我乘以另一个整数时,我会得到一个介于 0 和该整数之间的值。注意:我知道有一个函数可以在 0 和数字之间显式执行此操作,但我正在编写的代码最好每次都乘以一个随机数。
提前致谢。
【问题讨论】:
std::uniform_real_distribution<>(0.0,1.0)
?
警告:使用rand()
is highly problematic,我们强烈建议您使用合适的random number generator facility in the Standard Library,以产生高质量的随机值。您使用time(NULL)
作为随机数种子意味着如果在同一秒内运行,这将产生相同的结果,并且在许多平台上rand()
是barely random at all。
理论上,如果我将其更改为此处所述的均匀真实分布,它会解决问题吗? --挖掘漫画顺便说一句
在这里查看why you should call srand() only once。
不幸的是,这个帖子上有很多关于 RNG 好坏的噪音。但很可能最大的问题是@CostantinoGrana 指出的问题:您应该只在程序开始时调用srand()
一次,而不是每次在您的方法中。即使您使用更好的 PRNG,按照您的方式播种仍然会破坏它的随机性。
【参考方案1】:
最好的方法是使用 C++ 的随机数库,不是rand()
。
我们可以很容易地做到这一点:
#include <random>
double randomnumber()
// Making rng static ensures that it stays the same
// Between different invocations of the function
static std::default_random_engine rng;
std::uniform_real_distribution<double> dist(0.0, 1.0);
return dist(rng);
这将每次生成一个新的随机数,并且每次运行程序时都会生成相同的随机数序列。如果我运行
int main()
for(int i = 0; i < 10; i++)
std::cout << randomnumber() << '\n';
那我看看
0.131538
0.45865
0.218959
0.678865
0.934693
0.519416
0.0345721
0.5297
0.00769819
0.0668422
随机初始化生成器。如果您想在每次运行程序时生成不同的随机数,则必须使用随机种子初始化生成器。生成一个非常容易:
auto getRandomSeed()
-> std::seed_seq
// This gets a source of actual, honest-to-god randomness
std::random_device source;
// Here, we fill an array of random data from the source
unsigned int random_data[10];
for(auto& elem : random_data)
elem = source();
// this creates the random seed sequence out of the random data
return std::seed_seq(random_data + 0, random_data + 10);
一旦我们有了这个种子,我们就可以修改randomnumber()
来创建带有随机种子的生成器:
#include <random>
double randomnumber()
// Making rng static ensures that it stays the same
// Between different invocations of the function
static auto seed = getRandomSeed();
static std::default_random_engine rng(seed);
std::uniform_real_distribution<double> dist(0.0, 1.0);
return dist(rng);
【讨论】:
【参考方案2】:您的代码中一切正常 - 也许您对结果进行了取整而没有注意到更改。运行程序在第 4 位小数后依次变化双倍。 在我的平台中,从 time(...) 返回的 time_t 正在缩小转换为 unsigned int - 检查这一点。并且种子生成器一次就足够了 - 不是每个 randomnumber() 调用。您写道,您将结果用于蒙特卡罗模拟 - 生产中的蒙特卡罗模拟需要高质量的随机数 - 而不是 rand() 可能产生的。
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <iostream>
double randomnumber()
double r1 = (double)rand() / RAND_MAX;
return r1;
int main()
srand(time(NULL));
std::cout << randomnumber() << std::endl;
【讨论】:
以上是关于RNG 函数 C++的主要内容,如果未能解决你的问题,请参考以下文章