所以我试图创建一个“真正的”随机函数,因为rand不是随机的imo。
你认为这是获得随机数的“好方法”吗?如果不是,为什么?
int realrand() {
double duration = 0;
int i = 0;
std::clock_t start;
start = std::clock();
while(duration < 0.001) {
i++;
duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
}
int rand = i % 10;
return rand;
}
答案 0 :(得分:7)
两件事。
您的随机数生成器真的慢。
在我的笔记本电脑上计算C ++ 11和C样式rng 10000次约需0.016秒。将代码添加到混合中会将成本提高到 10秒!
您正在创建的随机数的分布很糟糕。
You C++11 rand()
0: 9615 9007 9006
1: 9143 9086 9008
2: 8650 8929 8958
3: 7907 9094 9114
4: 7943 9022 9021
5: 8098 8968 9005
6: 8676 8991 8810
7: 9970 8946 8903
8: 10061 8908 9094
9: 9938 9050 9082
让我们在直方图中显示这些数据。请注意,C和C ++实现在每个存储桶中具有大约相同数量的元素。另一方面,您的代码显然更喜欢输出0,7,8或9。
以下是我用来确定这个问题的一些代码:
#include <random>
#include <map>
int realrand() {
double duration = 0;
int i = 0;
std::clock_t start;
start = std::clock();
while(duration < 0.001) {
i++;
duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
}
int rand = i % 10;
return rand;
}
int cpprand() {
static std::random_device rd;
static std::mt19937 rng(rd());
static std::uniform_int_distribution<> dist(0, 9);
return dist(rng);
}
int crand() {
static int once = []() {
srand(time(NULL));
return 0;
}();
return rand() % 10;
}
int main() {
std::map<int, int> realrand_distribution;
std::map<int, int> cpprand_distribution;
std::map<int, int> crand_distribution;
for (int i=0; i<10000; ++i) {
realrand_distribution[realrand()]++;
cpprand_distribution[cpprand()]++;
crand_distribution[crand()]++;
}
for (int i=0; i<10; ++i) {
printf("%d: %10d %10d %10d\n", i, realrand_distribution[i], cpprand_distribution[i], crand_distribution[i]);
}
}
这是我用来生成直方图的代码:
import numpy
import pylab
x = numpy.arange(10)
width = 0.27
rects1 = pylab.bar(x+0*width, [9615, 9143, 8650, 7907, 7943, 8098, 8676, 9970, 10061, 9938], width, color='r')
rects2 = pylab.bar(x+1*width, [9007, 9086, 8929, 9094, 9022, 8968, 8991, 8946, 8908, 9050], width, color='b')
rects3 = pylab.bar(x+2*width, [9006, 9008, 8958, 9114, 9021, 9005, 8810, 8903, 9094, 9082], width, color='g')
pylab.legend([rects1, rects2, rects3], ["You", "C++", "C"])
pylab.show()
答案 1 :(得分:1)
要获得随机数(优于rand()
/ random()
/ etc),您需要使用库。有很多可用的东西,而C ++使一些基本的东西变得容易。
如上所述,std::random_device
存在问题。不幸的是,比人们意识到的更多 。
如果你想要真正随机的数字,你现在最好使用特定于系统的方法来获取它们:Mac和Linux上的/dev/urandom
以及Windows上的CryptoAPI。
你可以轻松地使用TRNG初始化(“种子”)PRNG,如XORShift,Mersenne Twister等。如果你需要CSPRNG,请使用加密库,但是对于其他所有这些都可以。
如果可以避免,请不要从时钟播种。它远没有人们想象的那么“随机”。无论你做什么,都要忽略使用带有PID等的哈希值的废话。
希望这有帮助。