C拼图:用有偏见的硬币做一个公平的硬币

时间:2011-03-25 05:56:59

标签: c algorithm math puzzle probability

在下列情况下,如何确定函数返回0或1的概率:

  

function_A返回0   概率为40%,概率为1   60%。生成function_B   概率50-50仅使用function_A   仅

我想到了以下内容:

 function_B()
 {
     int result1=function_A();
     int result2=function_A();
     //two times 40% would result in 16% and 40%+60% would be 24%... two times 60%                        would be 36%
 }

什么组合可以给50-50?

6 个答案:

答案 0 :(得分:70)

这是一个经典的概率难题,据我所知,只需要两次调用该函数就无法做到这一点。但是,您可以使用预期的函数调用次数来执行此操作。

观察结果是,如果你有一个有偏见的硬币出现概率为p的头部,如果你翻转硬币两次,那么:

  • 它出现两次头的概率是p 2
  • 它首先出现的概率和第二个出现的尾部的概率是p(1-p)
  • 它首先出现在尾部并且在第二个出现的概率是(1-p)p
  • 它出现两次尾巴的概率是(1-p) 2

现在,假设您反复翻转两个硬币,直到它们出现不同的值。如果发生这种情况,第一枚硬币出现的概率是多少?好吧,如果我们采用贝叶斯定律,我们就可以了解

P(第一个硬币是头|两个硬币不同)= P(两个硬币不同|第一个硬币是头)P(第一个硬币是头)/ P(两个硬币都不同)

第一枚硬币头部的概率是p,因为任何硬币投掷都会以概率p出现。考虑到第一枚硬币是头部,两个硬币不同的概率是第二枚硬币出现尾部的概率,即(1-p)。最后,两个硬币不同的概率是2p(1-p),因为如果你看一下上面的概率表,有两种方法可以发生,每种方法都有概率p(1-p)。简化,我们得到了

P(第一枚硬币是两个硬币不同)= p(1-p)/(2p(1-p))= 1/2。

但是,如果硬币不同,那么第一枚硬币出现尾巴的可能性是多少?嗯,这与两枚硬币不同时第一枚硬币未出现的概率相同,即1 - 1/2 = 1/2。

换句话说,如果你持续翻转两个硬币直到它们出现不同的值,那么你拿掉你翻转的第一枚硬币的价值,你最终会用一枚有偏见的硬币制作一枚硬币!

在C中,这可能如下所示:

bool FairCoinFromBiasedCoin() {
    bool coin1, coin2;

    do {
        coin1 = function_A();
        coin2 = function_A();
    } while (coin1 == coin2);

    return coin1;
}

这可能看起来非常低效,但实际上并没有那么糟糕。它在每次迭代时终止的概率是2p(1-p)。在期望中,这意味着在此循环终止之前我们需要1 /(2p(1-p))次迭代。对于p = 40%,这是1 /(2×0.4×0.6)= 1 /0.48~ = 2.083次迭代。每次迭代翻转两个硬币,因此我们需要大约4.16个硬币翻转以获得合理的翻转。

希望这有帮助!

答案 1 :(得分:8)

这是一种可行的方法,但需要反复试验。

<子>

  
      
  1. function_A返回1的机会:   P(1)= p(例如p = 60%)
  2.   
  3. function_A返回0的可能性:   P(0)= 1 - p
  4.   
  5. 特定序列的机会   连续返回值a,b,....   对function_A的来电是P(a) P(b) ...
  6.   
  7. 观察某些组合会   以相同的赔率出现,例如:

          P(a)*P(b) === P(b)*P(a)
     P(a)*P(b)*P(c) === P(b)*P(c)*P(a)
    
     etc.
    
  8.   
  9. 我们可以在选择时使用这个事实   然后我们接着(1,0)或(0,1)的序列   知道的机会是

        P(1)*P(0)/(P(1)*P(0) + P(0)*P(1)) 
     => x / (x + x)
     => 1 / 2
    
         

  10.   

然后,这成为了它的秘诀 实现一个function_B:

  • 反复拨打function_A直到我们 接收(0,1)或(1,0)
  • 的序列
  • 我们一直返回第一个或第一个 序列的最后一个元素(两者都将 等于0或1的几率)


function_B()
{
    do
    {
        int a = function_A();
        int b = function_A();
    } while( (a ^ b) == 0 ); // until a != b

    return a;
}

答案 2 :(得分:2)

<强>假设:

  1. Events = {head,tail}
  2. 硬币不公平=&gt; P(头)= p且P(尾)= 1-p
  3. <强>算法:

    1. 使用不公平的硬币生成N1事件(头部或尾部)的样本
    2. 估计其样本均值m1 =(#heads)/ N1
    3. 使用不公平的硬币生成另一个N2事件样本(头部或尾部)
    4. 估计其样本平均值m2 =(#heads)/ N2
    5. if(m1&gt; m2)返回head else return tail
    6. 备注:

      1. 上面步骤#5中返回的事件同样可能(P(头)= P(尾)= 0.5)
      2. 如果#5重复多次,则其样本均值 - > 0.5与p
      3. 无关
      4. 如果N1 - >无穷大,然后m1 - &gt;真实意思p
      5. 要生成公平的硬币输出,您需要对不公平硬币进行多次独立采样(此处为抛掷)。越多越好。
      6. 直觉:虽然硬币是不公平的,但估计均值在真实均值附近的偏差是随机的,可能是正或负,概率相等。由于未给出真实均值,因此可以从另一个样本中估算出来。

答案 3 :(得分:0)

可行的。但是,对这些功能的2次调用是不够的。想想一遍又一遍地调用函数并越来越接近50/50

答案 4 :(得分:0)

我想知道递归的东西是否应该起作用,随着深度的增加,0或1的机会应该越来越接近0.5。在1级,修正的机会是p'= p * p +(p-1)*(p-1)

depth = 10;
int coin(depth) {
    if (depth == 0) {
        return function_A();
    }
    p1 = coin(depth-1);
    p2 = coin(depth-1);
    if (p1 == p2) {
        return 1;
    } else {
        return 0;
    }
}

答案 5 :(得分:-1)

def fairCoin(biasedCoin):
coin1, coin2 = 0,0
while coin1 == coin2:
coin1, coin2 = biasedCoin(), biasedCoin()
return coin1

这最初是冯·诺依曼的聪明主意。如果我们有一个有偏见的硬币(即硬币出现的概率不同于1/2),我们可以通过掷硬币来模拟一个公平的硬币,直到两个结果不同为止。鉴于我们有不同的结果,第一个是“头”而第二个是“尾”的概率与“尾巴”然后“头”的概率相同。因此,如果我们简单地返回第一枚硬币的价值,我们将获得具有相同概率的“头”或“尾”,即1 / 2.这个答案来自 - http://jeremykun.com/2014/02/08/simulating-a-fair-coin-with-a-biased-coin/http://en.wikipedia.org/wiki/Fair_coin#Fair_results_from_a_biased_coin

了解更多相关信息