美文网首页
.NET 随机数Random()的坑

.NET 随机数Random()的坑

作者: Memoyu | 来源:发表于2019-07-11 10:50 被阅读0次

认知尚浅,如有错误,愿闻其详

概述

  在很多时候,我们系统中需要随机数去实现某些随机的功能,如果我告诉你,你一直在用的随机数不是“真随机数”,你信不信?

  • 首先,你可以先跑一下下面的循环:
    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);
        }

这样,我们得到的随机数才真正的可靠。

前辈的总结

  其实,除了地中生成随机数的方式不靠谱外,其余的两个都是可用,具体的使用还是看场景,相对于最后一种“真随机数”,第二种“伪随机数”的性能相对比较好,但是可靠性不如最后一种。

相关文章

网友评论

      本文标题:.NET 随机数Random()的坑

      本文链接:https://www.haomeiwen.com/subject/buxrkctx.html