随机数生成器(Random)的误用

很久以前发在公司内网的文章,发出来共享,隐去具体项目、人员的名字。

某日查一个bug,发现类似下面的代码
class Generator
{
...
  private StringBuffer generateRandStr(String strSet,int length)
  {
    StringBuffer sbuf = new StringBuffer() ;
    int charsetSize = strSet.length();
    Random random = new Random();
    for( int i = 0 ; i < length ; i++ )
    {
        //选择一个字符
    int index = random.nextInt( charsetSize ) ;
        char c = strSet.charAt(index);
        sbuf.append( c ) ;
    }
    return sbuf;
  }
...
}

这是一段生成随机字符串的程序,用于生成密码等场合,代码很简单也很清晰,但这里隐藏这一个bug,现象是连续多次调用这个方法产生的结果很多时候是相同的,如果传入的参数一样的话。
原因是什么呢?看到Random,我想到了伪随机数的问题,我们知道计算机算出的随机数通常称之为伪随机数,因为它实际上并不是完全随机的,只要确定了算法和种子,那么产生的随机数是固定的序列,再看一下Random的javadoc就更清楚了:
An instance of this class is used to generate a stream of pseudorandom numbers. The class uses a 48-bit seed, which is modified using a linear congruential formula. (See Donald Knuth, The Art of Computer Programming, Volume 2, Section 3.2.1.)

If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers.

如果连续调用发生在同一毫秒内,就意味着创建的随机数发生器的种子相同,那么结果就是相同的。养成阅读javadoc的习惯可以减少很多出错的机会。

你可能感兴趣的:(C++,c,算法,C#)