random随机数生成器和如何根据一个1-5的整数发生器得到1-7的整数发生器
- Math.random随机等概率生成
[0,1)之间的数字,因为在计算机中表示的数字长度是有限的,所以可以等概率 - 如果希望生成的数字的概率不是等概率,而是x2的概率出现,可以分别求两次random然后取最大值即可
- 如何根据一个等概率生成1-5的随机数发生器得到一个1-7等概率的随机数发生器?
/**
* 随机数发生器
* @returns 对[0, 1)之间数字的概率是 x2
*/
const randomX2 = () => {
return Math.max(Math.random(), Math.random())
}
let count = 0;
for (let i = 0; i < 1000000; i++) {
if (randomX2() < 0.5) {
count++
}
}
console.log('随机数生成小于0.5随机数的概率是:' + count / 1000000, '实际的概率应该是:', 0.5 * 0.5);
那么如果函数内是min会是什么效果?
/**
* 随机数发射器
* @returns 返回值是对 [0, 1) 之间的数字概率是 (1 - x)2 只要有一个在 [0, x) 范围 得到的结果就是 x
*/
const randomBackX = () => {
return Math.min(Math.random(), Math.random())
}
let count = 0;
for (let i = 0; i < 1000000; i++) {
if (randomBackX() < 0.5) {
count++
}
}
console.log('随机数生成小于0.5随机数的概率是:' + count / 1000000, '实际的概率应该是:', 1 - 0.5 * 0.5);
我们使用f函数得到一个1..7之间整数等概率出现的g函数
下面是f函数,假如我们只能用这个函数:
/**
* 随机数发送器
* @returns 等概率生成 1..5整数的发射器
*/
const f = () => {
return parseInt(Math.random() * 5 + '') + 1
}
我们需要用该函数去生成g函数: 像这样:
/**
* 利用f函数,得到下面的效果
* @returns 得到 1..7之间的整数等概率发生器
*/
const g = () => {
// f函数 1-5 五个数字 12 认为是0 45认为是1 3扔掉
const random01 = () => {
let ans: number;
do {
ans = f();
} while(ans === 3)
return ans >= 4 ? 1 : 0;
}
// 调用三次 random01 -> 结果当做二进制 000...111 8位
let ans: number
do {
ans = (random01() << 2) + (random01() << 1) + random01()
} while(ans === 0) // 我们要的是 1..7 不需要0 扔掉
return ans
}
const arr = new Array(7).fill(0)
for (let i = 0; i < 1_000_000; i++) {
arr[g() - 1]++
}
console.log("arr = ", arr);
你会发现我们做到了,确实是等概率的。