【发布时间】:2018-10-21 07:17:55
【问题描述】:
我正在运行以下程序:
#include <iostream>
#include <vector>
#include <cmath>
#include <cstdlib>
#include <chrono>
using namespace std;
const int N = 200; // Number of tests.
const int M = 2000000; // Number of pseudo-random values generated per test.
const int VALS = 2; // Number of possible values (values from 0 to VALS-1).
const int ESP = M / VALS; // Expected number of appearances of each value per test.
int main() {
for (int i = 0; i < N; ++i) {
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
srand(seed);
vector<int> hist(VALS, 0);
for (int j = 0; j < M; ++j) ++hist[rand() % VALS];
int Y = 0;
for (int j = 0; j < VALS; ++j) Y += abs(hist[j] - ESP);
cout << Y << endl;
}
}
此程序执行 N 次测试。在每个测试中,我们生成介于 0 和 VALS-1 之间的 M 个数字,同时我们不断计算它们在直方图中的出现次数。最后,我们在 Y 中累积误差,这些误差对应于直方图的每个值与期望值之间的差异。由于这些数字是随机生成的,因此理想情况下,每个测试都会出现 M/VALS 次。
运行我的程序后,我分析了结果数据(即 Y 的 200 个值),我意识到发生了一些我无法解释的事情。我看到,如果程序用 vc++ 编译并给出一些 N 和 VALS(在这种情况下 N = 200 和 VALS = 2),对于不同的 M 值,我们会得到不同的数据模式。对于某些测试,结果数据遵循正常分布,而对于某些测试,它没有。此外,这种类型的结果似乎会随着 M(每次测试中生成的伪随机值的数量)的增加而变化:
- M = 10K,数据不正常:
- M = 100K,数据正常:
- 等等:
如您所见,根据 M 的值,生成的数据服从正态分布或服从非正态分布(双峰、狗粮或均匀分布),其中 Y 的更极端值具有更大的存在。
如果我们使用其他 C++ 编译器(gcc 和 clang)编译程序,则不会出现这种结果的多样性。在这种情况下,看起来我们总是获得 Y 值的半正态分布:
您对此有何看法?解释是什么?
我通过这个在线编译器进行了测试:http://rextester.com/l/cpp_online_compiler_visual
【问题讨论】:
-
好的,但是我的问题呢。
-
rand()MSVC uses an extremely poor PRNG。它是一个线性同余生成器(非常简单但不是很随机),并且只输出 16 位数字。 -
在
std::rand(MSVC 版本)webhome.phy.duke.edu/~rgb/General/dieharder.php 上运行这个测试套件,然后发现你并没有真正的随机数生成器。所以这是一个垃圾箱等......
标签: c++ visual-c++ random statistics