Random number part1

如何利用一个小范围随机数生成一个大范围的随机数

用一个5以内的随机数函数生成一个7以内的随机数函数

1
var rand5 = () => ~~(Math.random()*5) // 利用这个函数生成5以内的随机数

这题的解题思路很简单, 只要利用这个函数生成一个平均分布的范围大于7的随机数就可以了

1
2
3
4
5
6
7
8
9
10
var rand7 = function() {
var val = rand5()*5 + rand5() // 平均分布 6~30 所以标准范围是6~26
return val>26?rand7():val%7+1 // 27~30之间的数据全部抛弃重新随机
}
var b = [0,0,0,0,0,0,0,0,]
for(var i=0; i<100000000;i++) {
b[rand7()]++
// [0, 14286297, 14287880, 14282580, 14287830, 14278935, 14285595, 14290883]
// 从数据看出是随机的
}

延伸: 如何利用一个小范围随机数生成一个大范围的随机数

重点在于如何保证随机数的平均分布
rand5()*5 + rand5() 可以看出实现的原理是先生成一个[5,10,15,20,25]间隔为5的随机数组后再使用一个随机数去填充这个数组, 那么对于更大范围的数比如一个大于25的数, 就需要rang5()*5*5+rand5()*5+rand5() 得到一个区间是 31~155 总的范围长度为125的数组
所以只需要递归获得一个大于范围的数组长度, 就可以得到一个由小范围随机数生成的大范围随机数, 具体代码就不贴出来了, 有兴趣可以自己实现一下

1
2
3
4
5
6
7
8
9
10
// 这里给出一个我偶然想到的阶乘
const factorial = function(n, x, num=n) {
// n 是对应的进制
// x 表示进位的长度
// num 表示被用于做乘法的数
// 所以 factorial(n, x, num) = num * n^x
const val = num.toString(n)
return x?parseInt(val.padEnd(val.length+x,"0"),n):1
}
console.log(factorial(2, 4, 5) === 5<<4) // true