如果我有一个名为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。
答案 0 :(得分:13)
生成两个数字,a
和b
。
如果a
为0且b
为1(机率为21%),则生成0
如果a
为1且b
为0(机率为21%),则生成1。
对于所有其他情况(58%的可能性),只需生成新的a
和b
,然后重试。
答案 1 :(得分:4)
如果您拨打rand1
两次,则获得[1 0]
和[0 1]
的机会相等,因此如果您返回每个不匹配对中的第一个(并丢弃匹配对)平均而言,每个输入位0.5(1 - p2 - (1-p)2)
输出位(p
是rand1
返回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%,但它永远不会完全相同。
如果你想要概率的数学:
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%
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%