使用单因素或多因素求解算法进行硬币翻转?

时间:2018-06-30 23:03:38

标签: algorithm random

使用单因素求解算法,使用硬币翻转生成1至9的随机整数是否更快,或者使用多因素求解算法在计算上更快?

使用一个因式分解进行求解,可以用f(2)的四个实例处理求解尝试,以获得4位/进程返回,其函数范围为2 ^ 4 = 16。为了按照该方法使用f(2)从1到9生成一个int,16个结果中的9个将是有效的,而每次求解尝试的7种可能的回报将是尝试失败/重试。因此,这种从1到9生成rand int的单一分解方法对四个过程函数具有7/16 =%44的解决尝试失败/重试率。

通过算法替代使用多个因素,可以相对减少求解尝试失败/重试的次数?

首先,f(2)的两个实例可以生成一个1到4的随机整数,仅接受从1到3的返回值,并且两个过程求解尝试函数的求解尝试失败/重试率均为%25。

接下来,f(2)的另外两个实例可以生成另一个从1到4的随机整数,仅接受从1到3的返回值,并且其两个过程求解尝试函数的求解成功率/重试率分别为%25。 / p>

从1到3的第一个兰特整数可以加到{3 *((从1到3个结果的第二个rand int)-1)}上,以产生从1到9的兰德整数,失败率为%25 / retry率,用于解决其前两个过程的尝试,然后%​​25失败/重试率,用于解决其后两个过程的尝试。

第二种算法的f(2)-> f(9)求解效率可能更高,因为它使用多个因素而不是一个因素?

有关通过掷硬币创建随机数生成器的讨论,请参见Creating a random number generator from a coin toss

1 个答案:

答案 0 :(得分:1)

平均而言,“多因素”方法肯定需要更少的随机位。

我将在下面给出完整的计算,但是要了解为什么要直观地考虑,请考虑以下因素:

  • 在单因素方法中,每组四个比特有9/16的机会给出有效结果;如果失败,则必须重新开始。
  • 在二因子方法中,每组四位(=两对两位)有9/16的机会给出完整的有效结果(=二有效因子);但即使失败,也有可能至少取得了一些进展,以后可以重用。

因此,从某种意义上说,两因素方法具有两个“成功之路”:

  • 成功的一组四位。
  • 一组成功的四位,后来又成功了一半。

单因素方法只有第一条路径。


现在,进行一些数学运算。 。

当给定的试验具有成功的概率 p 且所有试验都是独立的时,直到成功的预期试验次数为1 / p

此外,如果直到一个成功的预期试验次数为 N ,则直到 m 成功的预期试验次数为< em> mN 。

因此:

  • 当您的试验是“获得四个随机位”并且成功的定义是“结果在1到9之间”时,您可以预期需要16/9次试验,这意味着4·16/9 = 64/9≈ 7.11 随机位,然后再获得结果。
  • 当您的试验是“获得两个随机位”时,您对成功的定义是“结果在1到3之间”,并且您需要成功两次 ,那么您可能需要2次·4/3 = 8/3试用,表示2·8/3 = 16/3≈ 5.33 随机位,然后得到结果。

下面是一些可运行的JavaScript,尝试将这两种方法都进行10,000次,然后根据平均位数和每次需要更少次数的试验次数进行比较。 (当然,由于它正在调用Math.random()来获取每一位,因此这是“不现实的”,因为它要求一堆随机位,然后丢弃其中的大多数位。我仅将其包括在概念验证中数学,而不是实现这两种方法的实际示例代码。)

alert((function () {

var totalNumBitsEverGotten = 0;

function getBit() {
  ++totalNumBitsEverGotten;
  return Math.random() < 0.5 ? 0 : 1;
}

function getNBits(n) {
  var result = 0;
  for (var i = 0; i < n; ++i) {
    result = 2 * result + getBit();
  }
  return result;
}

function getIntInRange(min, max) {
  if (min != 0) {
    return getIntInRange(0, max - min) + min;
  }
  var numBitsNeeded = 0;
  for (var tmp = max; tmp > 0; tmp >>= 1) {
    ++numBitsNeeded;
  }
  while (true) {
    var nBits = getNBits(numBitsNeeded);
    if (nBits <= max) {
      return nBits;
    }
  }
}

function countBitsToGet1To9_approach1() {
  var numBitsPreviouslyGotten = totalNumBitsEverGotten;
  getIntInRange(1, 9);
  return totalNumBitsEverGotten - numBitsPreviouslyGotten;
}

function countBitsToGet1To9_approach2() {
  var numBitsPreviouslyGotten = totalNumBitsEverGotten;
  getIntInRange(1, 3);
  getIntInRange(1, 3);
  return totalNumBitsEverGotten - numBitsPreviouslyGotten;
}

var NUM_TRIALS = 10000;

var approach1Sum = 0;
var approach2Sum = 0;

var approach1Wins = 0;
var approach2Wins = 0;

for (var i = 0; i < NUM_TRIALS; ++i) {
  var approach1 = countBitsToGet1To9_approach1();
  var approach2 = countBitsToGet1To9_approach2();

  approach1Sum += approach1;
  approach2Sum += approach2;

  if (approach1 < approach2) {
    ++approach1Wins;
  } else if (approach2 < approach1) {
    ++approach2Wins;
  }
}

return 'After ' + NUM_TRIALS + ' trials:\n' +
       '- Approach #1 average: ' + (approach1Sum / NUM_TRIALS) + ' bits.\n' +
       '- Approach #2 average: ' + (approach2Sum / NUM_TRIALS) + ' bits.\n' +
       '- Approach #1 was faster in ' + approach1Wins + ' trial(s).\n' +
       '- Approach #2 was faster in ' + approach2Wins + ' trial(s).\n' +
       '- The two approaches tied in ' + (NUM_TRIALS - approach1Wins - approach2Wins) + ' trial(s).\n';

})());