认知尚浅,如有错误,愿闻其详
概述
在很多时候,我们系统中需要随机数去实现某些随机的功能,如果我告诉你,你一直在用的随机数不是“真随机数”,你信不信?
- 首先,你可以先跑一下下面的循环:
for (int i = 0; i < 1000; i++)
{
Console.WriteLine(new Random().Next(1, 1000));
}
"随机数".png
- 听说,把Random方法放到循环外效果更好?
Random r = new Random();
for (int i = 0; i < 1000; i++)
{
Console.WriteLine(r.Next(1000));
}
"听说随机数".png
看似真得随机数了,可是事实并不是如此。
内部实现
生成随机数的算法有很多种,最简单也是最常用的就是 "线性同余法":
第n+1个数=(第n个数*a+b) % c。
- 其中%是求余数运算符,c就是限制“第n+1个数”的得数不超过c。
- a,b则是两个常数,是随机数的因子。
- 第n个数为随机数种子,且随机数方法默认以时间为随机种子。
在编程里,时间精度终究有限,短时间内多次取出时间,这个时间值就可能重复,所以造成了上述的伪随机数。
内部详情请点我。感谢:gx_up
实现真随机数
Random(int seed)
该方法提供了带种子参数方法,便于开发者自己传入随机数种子,我们使用微软提供的加密服务system.Security.Cryptography.RNGCryptoServiceProvider
,生成随机加密数据,RNGCryptoServiceProvider
类它采用系统当前的硬件信息、进程信息、线程信息、系统启动时间和当前精确时间作为填充因子,通过更好的算法生成高质量的随机数。
Random rd = new Random(GetRandomSeed());
static int GetRandomSeed()
{
//字节数组,用于存储
byte[] bytes = new byte[4];
//创建加密服务,实现加密随机数生成器
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
//加密数据存入字节数组
rng.GetBytes(bytes);
//转成整型数据返回,作为随机数生成种子
return BitConverter.ToInt32(bytes, 0);
}
这样,我们得到的随机数才真正的可靠。
前辈的总结
其实,除了地中生成随机数的方式不靠谱外,其余的两个都是可用,具体的使用还是看场景,相对于最后一种“真随机数”,第二种“伪随机数”的性能相对比较好,但是可靠性不如最后一种。
网友评论