std::uniform_real_distribution 在失去随机性之前可以生成多少个随机数?
How many random numbers can std::uniform_real_distribution generate before losing randomness?
我正在为 Monte Carlo 模拟编写 C++ 代码。因此,我需要生成许多均匀分布在 [0,1) 之间的数字。我包含了以下取自 here 的代码来生成我的号码:
// uniform_real_distribution
#include <iostream>
#include <random>
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(0.0,1.0);
int main()
{
double number = distribution(generator); //rnd number uniformly distributed between [0,1)
return 0;
}
因此,每次我需要一个新号码时,我都会拨打 distribution(generator)
。
我 运行 我的 Monte Carlo 模拟得到很多样本结果。结果应该围绕真实平均值(未知)呈正态分布。当我 运行 进行卡方拟合优度检验以检查它们是否呈正态分布时,我的样本结果有时无法通过检验。这里的关键词是 "sometimes",所以这让我觉得我调用了 distribution(generator)
太多次,最后我失去了生成数字的随机性。我说的是每次模拟中生成的 10^11 个数字。
这可能吗?如果我在调用它之前用 distribution.reset()
重置分配怎么办?这能解决我的问题吗?
感谢您的任何建议。
STL使用的随机数生成算法在标准中没有规定,所以在不知道使用的随机数生成算法的情况下,无法确定随机序列有多长。
它可能是 Mersenne twister 或 CMWC 等一小部分已知的又好又快的发电机之一。
对随机数生成器进行评级的方法有很多种,但在你的问题中,我认为你想知道周期 - 数字重复之前的时间。该周期也将取决于初始条件。
一个很好的标准 CMWC 发生器,CMWC 4096 的周期为 2^131104。标准梅森发生器 MT19937 的周期为 2^19937。
但是,如果您使用的 STL 实现使用了选择不当的算法,那么所有的赌注都会落空。
在每次调用之前重新播种,甚至经常重新播种,特别是如果种子选择不当,将会破坏生成器的统计属性。通常最好只播种一次,然后从那里调用它。
如果随机数生成器有时没有通过测试,那么测试太弱了。例如,如果一个测试有 99% 的置信度,那么一个完美的随机数生成器应该有大约 1% 的概率会失败。
例如,考虑一枚完全公平的硬币。如果翻转 1,000 次,平均会出现 500 次正面朝上。如果你想用它来测试随机性,你可以计算一个公平硬币在一定时间百分比内落入的值范围。然后确保您的随机数生成器不会比预期更频繁地失败测试。
您的测试方法——期望随机数生成器每次都能通过每个测试——只有在您的测试非常弱时才有效。这将使糟糕的随机数生成器过于频繁地通过,这不是一种好的测试方法。
真实故事:我实现的一个随机数生成器经过 an independent testing lab 的严格测试。他们对其进行了 100 次测试,每次测试使用数百万个样本并测试各种特性。每个测试都有 99% 的置信度。 RNG通过了3次测试,均在预期范围内,因此通过了认证的测试部分。一个 RNG 在绝大多数时间都通过了这些极其严格的测试,这表明它是一个非常非常好的 RNG,也许是完美的。很难编写一个通过任何这些测试的损坏的 RNG。
您需要计算完美 RNG 无法通过测试的概率,然后查看您的 RNG 显示的失败率是否接近预期。
请注意,随机序列的强度取决于生成器,而不是分布。
关于 default_random_engine
the reference 说“一种发电机,至少可以为相对随意、不专业、and/or 轻量级使用提供可接受的引擎行为"...可能不是你想要的。
按照提示,可以换成std::mt19937
,我不是专家,不知道能用多久才会失去随机性。
要更新生成器的随机性,您可以使用 std::random_device
并不时将其用于 seed()
生成器。在某些实现中(您必须检查)random_device
甚至使用 CPU 的特殊指令来生成 "hard" 随机数作为种子。 las,您不能每次都简单地重新播种,因为这样的硬件生成速度非常慢。
我正在为 Monte Carlo 模拟编写 C++ 代码。因此,我需要生成许多均匀分布在 [0,1) 之间的数字。我包含了以下取自 here 的代码来生成我的号码:
// uniform_real_distribution
#include <iostream>
#include <random>
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(0.0,1.0);
int main()
{
double number = distribution(generator); //rnd number uniformly distributed between [0,1)
return 0;
}
因此,每次我需要一个新号码时,我都会拨打 distribution(generator)
。
我 运行 我的 Monte Carlo 模拟得到很多样本结果。结果应该围绕真实平均值(未知)呈正态分布。当我 运行 进行卡方拟合优度检验以检查它们是否呈正态分布时,我的样本结果有时无法通过检验。这里的关键词是 "sometimes",所以这让我觉得我调用了 distribution(generator)
太多次,最后我失去了生成数字的随机性。我说的是每次模拟中生成的 10^11 个数字。
这可能吗?如果我在调用它之前用 distribution.reset()
重置分配怎么办?这能解决我的问题吗?
感谢您的任何建议。
STL使用的随机数生成算法在标准中没有规定,所以在不知道使用的随机数生成算法的情况下,无法确定随机序列有多长。
它可能是 Mersenne twister 或 CMWC 等一小部分已知的又好又快的发电机之一。
对随机数生成器进行评级的方法有很多种,但在你的问题中,我认为你想知道周期 - 数字重复之前的时间。该周期也将取决于初始条件。
一个很好的标准 CMWC 发生器,CMWC 4096 的周期为 2^131104。标准梅森发生器 MT19937 的周期为 2^19937。
但是,如果您使用的 STL 实现使用了选择不当的算法,那么所有的赌注都会落空。
在每次调用之前重新播种,甚至经常重新播种,特别是如果种子选择不当,将会破坏生成器的统计属性。通常最好只播种一次,然后从那里调用它。
如果随机数生成器有时没有通过测试,那么测试太弱了。例如,如果一个测试有 99% 的置信度,那么一个完美的随机数生成器应该有大约 1% 的概率会失败。
例如,考虑一枚完全公平的硬币。如果翻转 1,000 次,平均会出现 500 次正面朝上。如果你想用它来测试随机性,你可以计算一个公平硬币在一定时间百分比内落入的值范围。然后确保您的随机数生成器不会比预期更频繁地失败测试。
您的测试方法——期望随机数生成器每次都能通过每个测试——只有在您的测试非常弱时才有效。这将使糟糕的随机数生成器过于频繁地通过,这不是一种好的测试方法。
真实故事:我实现的一个随机数生成器经过 an independent testing lab 的严格测试。他们对其进行了 100 次测试,每次测试使用数百万个样本并测试各种特性。每个测试都有 99% 的置信度。 RNG通过了3次测试,均在预期范围内,因此通过了认证的测试部分。一个 RNG 在绝大多数时间都通过了这些极其严格的测试,这表明它是一个非常非常好的 RNG,也许是完美的。很难编写一个通过任何这些测试的损坏的 RNG。
您需要计算完美 RNG 无法通过测试的概率,然后查看您的 RNG 显示的失败率是否接近预期。
请注意,随机序列的强度取决于生成器,而不是分布。
关于 default_random_engine
the reference 说“一种发电机,至少可以为相对随意、不专业、and/or 轻量级使用提供可接受的引擎行为"...可能不是你想要的。
按照提示,可以换成std::mt19937
,我不是专家,不知道能用多久才会失去随机性。
要更新生成器的随机性,您可以使用 std::random_device
并不时将其用于 seed()
生成器。在某些实现中(您必须检查)random_device
甚至使用 CPU 的特殊指令来生成 "hard" 随机数作为种子。 las,您不能每次都简单地重新播种,因为这样的硬件生成速度非常慢。