前言
前两天在写“随机报数机”的时候,用到了 Random 类,来生成随机数,发现一个现象:有时候 Random 类出来的数字连着好几次都是一样的,我就在想,这个数字到底是不是“随机”生成的,于是做了一个小实验。
实验
代码思路:新建一个线程,线程无线循环,每循环一次,由 Random 类生成一个随机数,根据随机数的值,让与数值对应的 panel 控件向上移动一个单位,就形成了类似于柱状图实时统计的效果。
这个时候,Random random = new Random(); 这句代码,放在不同的位置,就有两种不同的效果。为了让程序跑的快一些,我都尽量避免对界面的没有必要的访问。
第一种:Random random = new Random(); 放在循环外
最终的效果如下图所示,Random 类基本照顾到了范围内的所有数,整体基本平稳增加。
第二种:Random random = new Random(); 放在循环内
效果如下图所示,柱状图的上升非常突兀,整体不如第一种情况增长的平缓,差异很明显。
柱状图的突增说明 Random 类确实在一段时间内持续“宠幸”了某一个数,从画面看来就是某个柱状条的激增。
进一步实验
如果给循环加一个延时:
对于第一种情况:现象没有什么变化,也是平稳增加,只不过增加的慢了一点,这里就省略了。
对于第二种情况:表现发生了相当大的变化,代码如下所示:
interval 等于 1,就是加了 1 ms 的延时,速度慢了点,但是 Random 不再连续随机到某一个数,整体上升平稳。
后记
现象 1 :实例化对象的代码的位置不同,效果不同。
猜想 1 :可能是放在循环内部的时候,每次都是新实例化的对象,这样每个数被随机到的概率都是相同的(假设 Random 类真的完全模拟了自然随机事件)。放在循环外部,第二次的循环可能会有意避开第一次的循环。
现象 2 :实例化放在循环内部的时候,加了 1 ms 的延迟,Random 不再持续“宠幸”某一个数,打破了猜想 1。
猜想 2 :Random 类可能与时间有关。
猜想 3 :在控制台中,将实例化放在循环内,Random 类持续“宠幸”某个数的行为将更加严重,因为前后间隔时间更短。
若要查明真相,估计要查阅 Random 类的 源码,我点进去看了下,emmmmmm,以后再研究吧,还有别的事情要做[跑路]。
C语言里随机函数要调用当前时间,出来的随机数差距都不是很大。
后来知道时间方法有一个叫“种子”的东西,谢谢!