生成可预测的随机数
编辑教程生成可预测的随机数
问题
生成在一定范围内的随机数,但也需要对发生器进行“生成种子”操作来提供可预测的值。
解决方案
编写自己的随机数生成器。当然有很多方法可以做到这一点,这里给出一个简单的示例。 该发生器绝对不可以以加密为目的!
class Rand
# 如果没有种子创建,使用当前时间作为种子
constructor: (@seed) ->
# Knuth and Lewis' improvements to Park and Miller's LCPRNG
@multiplier = 1664525
@modulo = 4294967296 # 2**32-1;
@offset = 1013904223
unless @seed? && 0 <= seed < @modulo
@seed = (new Date().valueOf() * new Date().getMilliseconds()) % @modulo
# 设置新的种子值
seed: (seed) ->
@seed = seed
# 返回一个随机整数满足 0 <= n < @modulo
randn: ->
# new_seed = (a * seed + c) % m
@seed = (@multiplier*@seed + @offset) % @modulo
# 返回一个随机浮点满足 0 <= f < 1.0
randf: ->
this.randn() / @modulo
# 返回一个随机的整数满足 0 <= f < n
rand: (n) ->
Math.floor(this.randf() * n)
#返回一个随机的整数满足min <= f < max
rand2: (min, max) ->
min + this.rand(max-min)
讨论
JavaScript和CoffeeScript都不提供可产生随机数的发生器。编写发生器将是一个挑战,在于权衡量的随机性与发生器的简单性。
但是,对于这个随机数发生器只有简单的解释。这是一个线性同余伪随机数发生器,其运行源于一条数学公式Ij+1 = (aIj+c) % m,其中a是乘数,c是加法偏移量,m 是模数。每次请求随机数时就会执行很大的乘法和加法运算——这里的“很大”与密钥空间有关——得到的结果将以模数的形式被返回密钥空间。
这个发生器的周期为232。虽然它绝对不能以加密为目的,但是对于最简单的随机性要求来说,它是相当足够的。randn()在循环之前将遍历整个密钥空间,下一个数由上一个来确定。
不要把发生器的输出结果变成模数。如果需要一个整数的范围,应使用分割的方法。线性同余发生器的低位是不具有随机性的。特别的是,它总是从偶数种子产生奇数,反之亦然。所以如果需要一个随机的0或者1,不要使用:
# NOT random! Do not do this!
r.randn() % 2
肯定得不到随机数字,应使用r.rand(2)。
Mos固件,小电视必刷固件
ES6 教程
Vue.js 教程
JSON 教程
jQuery 教程
HTML 教程
HTML 5 教程
CSS 教程
CSS3 教程
JavaScript 教程
DHTML 教程
JSON在线格式化工具
JS在线运行
JSON解析格式化
jsfiddle中国国内版本
JS代码在线运行
PHP代码在线运行
Java代码在线运行
C语言代码在线运行
C++代码在线运行
Python代码在线运行
Go语言代码在线运行
C#代码在线运行
JSRUN闪电教程系统是国内最先开创的教程维护系统, 所有工程师都可以参与共同维护的闪电教程,让知识的积累变得统一完整、自成体系。
大家可以一起参与进共编,让零散的知识点帮助更多的人。
X
选择支付方式:
立即支付
¥
9.99
无法付款,请点击这里
金额: 0 元
备注:
转账时请填写正确的金额和备注信息,到账由人工处理,可能需要较长时间
备注:
转账时请填写正确的金额和备注信息,到账由人工处理,可能需要较长时间
如有疑问请联系QQ:565830900
正在生成二维码, 此过程可能需要15秒钟