🎲 随机数试验
Conmajia © 2012, 2018
Published on May 23rd, 2012
Updated on March 10th, 2018
这是重新排版的版本。
真随机和伪随机
随机数是计算机编程中一个非常重要的工具. 随机数够不够随机System.Random
来获得随机数. 从本质上讲Random
生成的不是真随机数
伪随机数
或称伪乱数 , 是使用一个确定性的算法计算出来的似乎是随机的数序 , 因此伪随机数实际上并不随机 , 在计算伪随机数时假如使用的开始值不变的话 。 那么伪随机数的数序也不变 , 伪随机数的随机性可以用它的统计特性来衡量 。 其主要特征是每个数出现的可能性和它出现时与数序中其它数的关系 , 伪随机数的优点是它的计算比较简单 。 而且只使用少数数值很难推算出计算它的算法 , 一般人们使用一个假的随机数 。 比如电脑上的时间作为计算伪随机数的开始值 , 。
几乎所有的真随机数发生器都具有专利保护. 下图列举了部分真随机数发生器专利.

理论上
System.Random
原理
System.Random
基于Random
可以利用种子进行随机化
关于试验
这次试验
Random rand;
while (true) {
// 用种子初始化随机数
rand = new Random (seed);
int value = rand.Next ();
// (费时的操作)
}
在未来超高速计算环境下Random
生成的数值
试验方法
模拟最严酷的环境rand
生成方式和 count
数Random
生成方式及相应的随机数生成结果进行对比.
// 示例代码,不可用
for (int i = 0; i < count; i++) {
rand.Next ();
}
试验条件 [2]
项目 | 配置 |
---|---|
CPU | i3 380m 2.56GHz 2 |
内存 | DDR3 1066 2GB x2 |
硬盘 | TOSHIBA MK3265GSX (320 GB) @ 5400 RPM |
运行时 | .NET Framework |
开发环境 | Visual Studio 2005 Team Suite |
操作系统 | Windows XP SP3 |
测试用例
这次试验针对以下 8 种常见的随机数生成方式进行测试
-
默认构造函数
使用Random rand=new Random()
. 单次生成 不重复. 这也是 MSDN 建议的生成方式., -
默认构造函数
重复创建( )
仍然使用默认构造函数 但是在每次循环中都重新创建, Random
变量. -
常数种子
使用rand=new Random(10)
. 用常数作为种子. -
常数种子
重复创建( )
类似用例 #2. -
时间刻度种子
这是比较普遍的一种用法 每次利用系统当前时间作为种子. 使用, DateTime.Now.Ticks
. 注意只能重复创建 否则将成为 #3., -
随机数种子
这是一种看起来很随机的方法 使用另一个, Random
变量 在每次循环时用, Next()
作为种子. 注意只能重复创建 否则将成为 #3., -
三角函数种子
使用Math.Sin()
作为种子. -
复杂种子
这是种子随机性比较大的一种方法 利用 GUID 哈希值, 当前时间、 Ticks
和计数器相乘来计算种子. 有很多高手推荐.
private static int randomCount = 0;
private static string CreateRandomText () {
randomCount++;
Guid guid = Guid.NewGuid ();
int key1 = guid.GetHashCode ();
int key2 = unchecked ((int)DateTime.Now.Ticks);
int seed = unchecked (key1 * key2 * randomCount);
Random rand = new Random (seed);
int n = rand.Next (100000, 999999);
// (业务代码,略)
}
试验原理
统计在生成范围内PictureBox
中绘制出统计直方图. 同时Random
的生成结果变化情况. 跳变数越多
试验程序的实现和代码和本文无关
试验结果样张说明
下面是两张测试样张


这是测试生成Width
Random
图中文字说明含义为
- 最大重复 同样的数值出现的最大次数
例如生成, 其中, 则最大重复为, - 跳变 当某次生成的随机数和前次不同
则跳变数, - 用时 生成全部随机数所用时间
该时间不含界面渲染花费的时间,
需要注意的是直方图的高度是自适应的
如何阅读样张
测试程序运行后得到的样张参见前一节的 Sample A 和 Sample B. 样图记录的是 Random
生成的随机数的重复次数统计
试验结果
每张测试结果样张中均包含全部 8 个测试用例





结果分析
#1 默认构造函数
默认构造函数单次创建的Random
#2 默认构造函数 ( 重复创建)
很差的随机性. 也展示出一个问题Random
#3 常数种子
使用常数完成初始化的 Random
#4 常数种子 ( 重复创建)
每次采用同样的种子创建 Random
Random
生成的第一个随机数index
Random
获取的并非真实随机数.
#5 时间刻度种子
对于高强度的生成DateTime.Ticks
的最小时间刻度为Random
时的时间种子 dump 出来观察DateTime.Now.Ticks
才会发生变化. 这导致输出的值域收缩了 20~50 倍.
#6 随机数种子
用 #1Random
的种子
#7 三角函数种子
使用 Math.Sin()
作为种子. 由于
#8 复杂种子
让人寄予厚望
总结
消耗众多资源Random
变量.
以上即是本人通过试验结果做出的简单推论
The End.

if(jQuery('#no-reward').text() == 'true') jQuery('.bottom-reward').addClass('hidden');
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?