zoukankan      html  css  js  c++  java
  • JS随机数生成算法浅析:9301、49297、233380做基数的原因

      见到这个随机数生成算法好几次了,乍看有点鸡肋,本来用Math.random()就可以的事,想不清楚为什么他要用9301,49297,233280这三个数字?其中有道理吗?还是仅是随意选的三个数?但是这个组合貌似流传很广,好多网站源码里都见到过。

    // 生成随机数
    export function generateRandom (number) {
      function rnd (seed) {
        seed = ( seed * 9301 + 49297 ) % 233280
        return seed / ( 233280.0 )
      }
      let today = new Date()
      let seed = today.getTime()
      return Math.ceil(rnd(seed) * number)
    }

      很多人认为这是简单的Magic Number,其实这背后有内在的原因,这三个数字并不是随便乱选出来的。

    1、入门级的选择标准

      这种伪随机数生成器叫做线性同余生成器(LCG, Linear Congruential Generator),几乎所有的运行库提供的rand都是采用的LCG,形如:[公式]

      生成的伪随机数序列最大周期m,范围在0到m-1之间。要达到这个最大周期,必须满足

    • c与m互质
    • a - 1可以被m的所有质因数整除
    • 如果m是4的倍数,a - 1也必须是4的倍数

      以上三条被称为Hull-Dobell定理。

      作为一个伪随机数生成器,周期不够大是不好意思混的,所以这是要求之一。可以看到,a=9301, c = 49297, m = 233280这组参数,以上三条全部满足。

    2、进阶级的选择标准

      要在伪随机数生成器界混,仅仅入门是不够的。

      从工程的角度来讲,[公式]的值要(在合理的范围内)足够小,以避免溢出的问题。

      从安全(实用)性的角度来讲,还要满足良好的随机性,这一点可以通过Knuth's Spectral Test来评估(见[2][3]),要通过2,3,4,5以及6维的Spectral Test才行。

      Spectral Test考察的就是生成的伪随机数序列在超空间的网格结构(lattice structure),当年IBM的RANDU子程序闹出的乌龙,连3维的Spectral Test就不能通过。

      其中每个点代表三个连续的RANDU生成的伪随机数值,可以看到所有伪随机数分布在了15个二维平面上。在这种要求面前,c的值最好:

    • 是质数 (c = 49297就是质数)
    • 接近[公式],(m = 233280时为49297.86460172205)

      所以有了这样一些基本的标准,能够选择的参数范围就小了很多,弄个程序跑下Spectral Test,就能得到可选的参数组。

      如果想要更加详尽的了解LCG伪随机数生成器的性质以及参数选取、测试的数学理论,可以尝试阅读《计算机程序设计艺术》卷2第3章。

  • 相关阅读:
    Linux-第一天
    Hadoop学习10--常用命令记录帖
    C# asp.net repeater实现排序功能,自动排序,点击头部排序,点击列排序
    图片与字符之间的转换
    兼容浏览器 div固定浏览器窗口底部 浮动div
    解决QQ未启用状态,QQ留言图标未启用
    C#Cookie操作类,删除Cookie,给Cookie赋值
    vs2008bin下Debug bll Release文件 obj下的Debug bll Release文件区别
    asp.net限制了上传文件大小为..M,解决方法
    多文件上传ajax jquery
  • 原文地址:https://www.cnblogs.com/goloving/p/13985017.html
Copyright © 2011-2022 走看看