how to create a random number

看似简单的一个题目,相信大部分人都会第一时间说出rand()函数,但是我们的做法真的正确么?生成的随机数确实真的随机么?

 

1. 看下面代码,用rand()生成随机数

int main(){
    cout<<"rand() traps by Sparkles."<<endl;
int N = 10; for (int i = 0; i < N; ++i) cout<< rand()%n; getchar(); return 0; }

结果如下:

  1. rand() traps by Sparkles.
  2. 1740948824

 

2. 似乎并没有什么异常,但是,如果多次运行程序,会发现,每次生成的结果都是一样的。

这个问题网上解释很充分,另见:http://www.cplusplus.com/reference/cstdlib/rand/ 

rand
int rand (void);
Generate random number

Returns a pseudo-random integral number in the range between 0 and RAND_MAX.

This number is generated by an algorithm that returns a sequence of apparently non-related numbers each time it is called. This algorithm uses a seed to generate the series, which should be initialized to some distinctive value using function srand.

上文提到,rand()算法是由一个seed来生成随机数的,可以通过srand()来定义这个seed。而一开始的例子中,并未调到srand(),所以rand()默认将1作为seed来生成随机数。(狗屎的节奏哇)

下面是通过设置seed来生成随机数,可以看到,当seed不同的时候,随机数结果会变化,最后一种将seed设置成time(0)是网上比较通用的做法。

int main(){
    int N = 10;
    cout<<"rand() traps by Sparkles."<<endl;
    cout<<"Set seed as 1\t\t\t";
    srand(1);
    for (int i = 0; i < N; ++i)
        cout<< rand()%N;
    
    cout<<endl<<"Set seed as 2\t\t\t";
    srand(2);
    for (int i = 0; i < N; ++i)
        cout<< rand()%N;

    cout<<endl<<"Set seed as current time\t";
    srand(time(0));
    for (int i = 0; i < N; ++i)
        cout<< rand()%N;
    getchar();
    return 0;
}
  1. rand() traps by Sparkles.
  2. Set seed as 1 1740948824
  3. Set seed as 2 5685400156
  4. Set seed as current time 1907157566

3.貌似完美解决, 但是,事情并没有那么简单,rand()生成伪随机数(returns a pseudo-random integral number),所谓伪随机数,意思就是并不是真的随机。在大多数领域,其实伪随机数就足够了,但是,有的情况下,伪随机数会成为一个漏洞,比如赌场的洗牌程序,如果利用伪随机数,那么假如黑客利用一台电脑,和赌场的电脑时钟完全同步,那么在同一个时间点,利用上面代码生成的随机数有可能是一样的,这样黑客有可能预测洗牌的结果。  

想要解决这个问题,一个办法是利用硬件来生成真随机数。这个原理暂且不提。除了单独的硬件外,目前通用的思路是,利用一些计算机外部的环境获取不可预知的数据,比如获取计算机周边的噪音,这个是非常难被人获取的,或者要求使用者随机移动鼠标,比如putty的RSA keygen。

 

 

http://winscp.net/eng/docs/ui_puttygen#generate

http://www.random.org/

posted @ 2014-04-06 15:00  Sparkles  阅读(183)  评论(0编辑  收藏  举报