from http://www.learncpp.com/cpp-tutorial/59-random-number-generation/
通常在游戏,统计模型程序和科学模拟中会用到随机事件。
而由于计算机的本质结构决定计算机只能生成伪随机数据。
伪随机生成器,设定一个初始值(seed),对它进行操作形成不同的数值,让它看上去与初始值没有联系。如果算法足够复杂,将同样的算法用到最后生成的数字,这样就能够产生一些列看上去随机的数值。
下面是一个产生100个伪随机数的程序:
1.
1: #include <stdafx.h>
2: #include <iostream>
3: using namespace std;
4:
5: unsigned int PRNG()
6: {
7: // our initial starting seed is 5323
8: static unsigned int nSeed = 5323;
9:
10: // Take the current seed and generate a new value from it
11: // Due to our use of large constants and overflow, it would be
12: // very hard for someone to predict what the next number is
13: // going to be from the previous one.
14: nSeed = (8253729 * nSeed + 2396403);
15:
16: // Take the seed and return a value between 0 and 32767
17: return nSeed % 32767;
18: }
19:
20: int main()
21: {
22: // Print 100 random numbers
23: for (int nCount=0; nCount < 100; ++nCount)
24: {
25: cout << PRNG() << "\t";
26:
27: // If we've printed 5 numbers, start a new column
28: if ((nCount+1) % 5 == 0)
29: cout << endl;
30: }
31: }
事实上我们这个例子并不是很好,但是它足够用来说明伪随机数是如何产生的。
C++产生伪随机数
语言中有内置的随机数生成器,它需要两个独立的函数组合使用。
srand() 用来设置初始seed。srand()通常只调用一次。
rand()生成序列中的下一个随机值。
2.
1: #include <iostream>
2: #include <cstdlib> // for rand() and srand()
3: using namespace std;
4:
5: int main()
6: {
7: srand(5323); // set initial seed value to 5323
8:
9: // Print 100 random numbers
10: for (int nCount=0; nCount < 100; ++nCount)
11: {
12: cout << rand() <<“\t”;
13:
14: // If we've printed 5 numbers, start a new column
15: if ((nCount+1) % 5 == 0)
16: cout << endl;
17: }
18: }
rand()产生的伪随机数的范围在0到RAND_MAX之间,通常它的值在cstdlib中为32767.
通常我们并不想要这个范围内的随机值。我们想要两个nLow和nHigh范围内。如1-6.
3.
1: // Generate a random number between nLow and nHigh (inclusive)
2: unsigned int GetRandomNumber(int nLow, int nHigh)
3: {
4: return (rand() % (nHigh - nLow + 1)) + nLow;
5: }
当我们反复运行第2个程序的时候,发现每次的结果都是相同的。由于我们每次设置的seed都是相同的。因此我们使用了time()函数来产生seed。
1: #include <stdafx.h>
2: #include <iostream>
3: #include <cstdlib> // for rand() and srand()
4: #include <ctime> // for time()
5: using namespace std;
6:
7: int main()
8: {
9:
10: srand(time(0)); // set initial seed value to system clock
11: for (int nCount=0; nCount < 100; ++nCount)
12: {
13: cout << rand() << "\t";
14:
15: if ((nCount+1) % 5 == 0)
16: cout << endl;
17: }
18: }
怎样的伪随机生成器算是好的呢?
1)生成器会以相同的概率产生每一个数值。
2)随机序列的下一个数字不能明显、容易被预测
3)随机数生成器产生的数值有一个好的分布,忽而小,忽而大,让人感觉是随机的。
4)所有的伪随机生成器都是周期性的
rand()函数只是一个普通的伪随机生成器
大多数rand()都是使用Linear Congruential Generator方法实现的。
由于RAND_MAX通常是32767,意味着如果我们想要更大的范围就会不适合了。同时,rand()也不适合产生浮点型随机值如0.0-1.0. 同时rand()相对于其他算法拥有一个短的周期。
可以使用Mersenne Twister,它具有更好的结果,同时使用相对简单。