如何编写一个函数来生成随机数0/1使用另一个随机函数?

时间:2012-08-25 12:51:41

标签: algorithm random numbers

如果我有一个名为rand1()的函数生成数字0(概率为30%)或1(概率为70%),如何编写生成数字0或1等概率的函数rand2()使用rand1()?< / p>

更新

最后,我发现这是一本关于算法入门(第2版)的问题(我已经买了这本书的中文版),练习5.1-3,原来的问题是:

5.1-3 假设您想以概率1/2输出0,以1/2输出概率1/2。 您可以使用BIASED-RANDOM程序,输出0或1 输出1具有一些概率p和0,概率为1p,其中0 <1。 p&lt; 1, 但你不知道p是什么。给出一个使用BIASED-RANDOM的算法 作为子程序,返回无偏答案,以概率1/2返回0 和1的概率为1/2。算法的预期运行时间是多少 作为p?

的函数

解决方案是: (见:http://www.cnblogs.com/meteorgan/archive/2012/05/04/2482317.html

要获得无偏的随机位,只需调用BIASED-RANDOM,即可调用 BIASED-RANDOM两次。反复这样做,直到两个呼叫返回不同 值,当发生这种情况时,返回两位中的第一位:

UNBIASED-RANDOM
while TRUE
do
x ← BIASED-RANDOM
y ← BIASED-RANDOM
if x != y
then return x

要看到UNBIASED-RANDOM以概率1/2返回0和1,请观察 给定迭代返回0的概率是

Pr {x = 0 and y = 1} = (1 − p)p ,

和给定迭代返回1的概率是

Pr {x = 1 and y = 0} = p(1 − p) .

(我们依赖于BIASED-RANDOM返回的比特是独立的。)因此, 给定迭代返回0的概率等于它返回1的概率。 由于UNBIASED-RANDOM没有其他方法可以返回值,因此返回0 和1,概率为1/2。

4 个答案:

答案 0 :(得分:13)

生成两个数字,ab

如果a为0且b为1(机率为21%),则生成0 如果a为1且b为0(机率为21%),则生成1。

对于所有其他情况(58%的可能性),只需生成新的ab,然后重试。

答案 1 :(得分:4)

如果您拨打rand1两次,则获得[1 0][0 1]的机会相等,因此如果您返回每个不匹配对中的第一个(并丢弃匹配对)平均而言,每个输入位0.5(1 - p2 - (1-p)2)输出位(prand1返回1的概率;在您的示例中为0.7)并且独立于{{ 1}},每个输出位将为1,概率为0.5。

然而,我们可以做得更好。

我们可以记住它们,而不是丢弃匹配的对,希望它们后面跟着相反的匹配对 - 序列p[0 0 1 1]也同样可能,我们又可以返回每当我们看到这样一个序列时仍然是第一位(输出概率为0.5)。我们可以无限期地组合它们,寻找像[1 1 0 0]等序列。

我们可以更进一步 - 考虑输入序列[0 0 0 0 1 1 1 1][0 0 0 1]产生相同的输出([0 1 0 0]),但这两个序列也同样可能,所以我们可以从中提取额外的输出,为第一个案例返回[0][0 0] 为了第二个。这是它变得更复杂的地方,因为你需要开始缓冲输出位。

这两种技术都可以递归应用,并且达到极限它变为无损(即如果[0 1]的概率为0.5,则每个输入位平均得到一个输出位。)

完整说明(带数学):http://www.eecs.harvard.edu/~michaelm/coinflipext.pdf

答案 2 :(得分:0)

低于rand2函数将提供50或0出现概率的概率为50%。

#define LIMIT_TO_CALCULATE_PROBABILITY 10 //set any even numbers

int rand2()
{
    static int one_occurred = 0;
    static int zero_occured = 0;
    int rand_value = 0;
    int limit = (LIMIT_TO_CALCULATE_PROBABILITY / 2);

    if (LIMIT_TO_CALCULATE_PROBABILITY == (one_occured + zero_occured))
    {
        one_occured = 0;
        zero_occured = 0;
    }

    rand_value = rand1();   

    if ((1 == rand_value) && (one_occured < limit))
    {
        one_occured++;
        return rand_value;
    }
    else if ((0 == rand_value) && (zero_occured < limit))
    {
        zero_occured++;
        return rand_value;
    }
    else if (1 == rand_value)
    {
        zero_occured++;
        return 0;
    }
    else if (0 == rand_value)
    {
        one_occured++;
        return 1;
    }   
}

答案 3 :(得分:0)

你需要弄清楚你想达到50%0 50%1的接近程度。

如果您将重复调用的结果添加到rand1。如果结果为0或2,则返回的值为0(如果为1)则返回1.(在代码中,您可以使用模2)

int val = rand1();   // prob 30%      0, and 70%      1

val=(val+rand1())%2; // prob 58%      0, and 42%      1  (#1 see math bellow)
val=(val+rand1())%2; // prob 46.8%    0, and 53.2%    1  (#2 see math bellow)
val=(val+rand1())%2; // prob 51.28%   0, and 48.72%   1
val=(val+rand1())%2; // prob 49.488%  0, and 50.512%  1
val=(val+rand1())%2; // prob 50.2048% 0, and 49.7952% 1

你明白了。因此,您需要弄清楚您想要概率的接近程度。每次后续通话都会让你接近50%50%,但它永远不会完全相同。

如果你想要概率的数学:

1

prob ((val+rand1()%2) = 0) = (prob(val = 0)*prob(rand1() = 0)) + (prob(val = 1)*prob(rand1() = 1)
                           = (0.3*0.3)+(0.7*0.7)
                           = 0.09 + 0.49
                           = 0.58
                           = 58%

prob ((val+rand1()%2) = 1) = (prob(val = 1)*prob(rand1() = 0)) + (prob(val = 0)*prob(rand1() = 1)
                           = (0.7*0.3)+(0.3*0.7)
                           = 0.21 + 0.21
                           = 0.42 
                           = 42%

2

 prob ((val+rand1()%2) = 0) = (prob(val = 0)*prob(rand1() = 0)) + (prob(val = 1)*prob(rand1() = 1)
                            = (0.58*0.3)+(0.42*0.7)
                            = 0.174 + 0.294
                            = 0.468
                            = 46.8%

 prob ((val+rand1()%2) = 1) = (prob(val = 1)*prob(rand1() = 0)) + (prob(val = 0)*prob(rand1() = 1)
                            = (0.42*0.3)+(0.58*0.7)
                            = 0.126 + 0.406
                            = 0.532
                            = 53.2%