random随机数生成器和如何根据一个1-5的整数发生器得到1-7的整数发生器

254 阅读2分钟

random随机数生成器和如何根据一个1-5的整数发生器得到1-7的整数发生器

  1. Math.random随机等概率生成[0,1)之间的数字,因为在计算机中表示的数字长度是有限的,所以可以等概率
  2. 如果希望生成的数字的概率不是等概率,而是x2的概率出现,可以分别求两次random然后取最大值即可
  3. 如何根据一个等概率生成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);

你会发现我们做到了,确实是等概率的。