使用单因素求解算法,使用硬币翻转生成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
答案 0 :(得分:1)
平均而言,“多因素”方法肯定需要更少的随机位。
我将在下面给出完整的计算,但是要了解为什么要直观地考虑,请考虑以下因素:
因此,从某种意义上说,两因素方法具有两个“成功之路”:
单因素方法只有第一条路径。
现在,进行一些数学运算。 。
当给定的试验具有成功的概率 p 且所有试验都是独立的时,直到成功的预期试验次数为1 / p 。
此外,如果直到一个成功的预期试验次数为 N ,则直到 m 成功的预期试验次数为< em> mN 。
因此:
下面是一些可运行的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';
})());