一枚均值硬币(fair coin),其概率分布为 [(0,0.5),(1,0.5)]
import random
def coin():
p = random.random()
return 1 if p < 0.5 else 0
产生0.25, 0.75的概率分布
投掷(toss)一枚硬币,正面向上为1
,反面向上为0
。连续投掷两次,11
为1:对应概率为0.25,{10, 01, 00}
为0:对应概率为0.75。也即此时的随机变量(rv,random variable)
X
为投掷两次的与(and)
值。
应用:A, B, C, D
的四个选项,用一枚硬币产生每个选项相等的概率,也即各位0.25.
A
:11
B
:10
C
:01
D
:00
def prob1():
a, b = coin(), coin()
if (a & b) == 1:
return 1
else:
return 0
测试:
import collections
cnt = collections.defaultdict(int)
N = 10**5
for i in range(N):
cnt[prob1()] += 1
for n in cnt:
print(n, cnt[n]/N)
# 0 0.749835
# 1 0.250165
产生 13,23 的概率分布
投掷一枚硬币两次,11
为1,{10, 01}
为0,{00}
重新投掷。
应用:自然是A, B, C
三个选项,用一枚硬币产生每个选项相等的概率。
def prob2():
while True:
a, b = coin(), coin()
if (a & b) == 1:
return 1
if (a | b) == 1:
return 0
# while 和 两个 if(但没有else)的结合很妙
# 实现对else情况的重新投掷判断
产生 0.3,0.7 的概率分布
投掷一枚硬币四次,前三种情况为1,也即{0000, 0001, 0010}
,再有六种情况为0,如{0011, 0100, 0101, 0110, 0111, 1000}
,其余情况重新投掷。
当然方案并不唯一。这里再提供一个利用条件概率解决方案,首先定义离散型随机变量 X :投掷一枚硬币四次得到的二进制表示(0000-1111)(如同掷一个骰子得到点数为1-6)。在点数不大于10的情况下点数不大于3的概率(这方案有点耍无赖,:-D)。
再转念一想,“点数不大于10的条件下”莫不就是把其他的情况排除了嘛,原来两种方案是等价的,只不过条件概率的概念可以解释第一种方案罢了。
def prob3():
while True:
a, b, c, d = coin(), coin(), coin(), coin()
if ...
如果是一个骰子呢?
如何通过一个掷骰子获得
其实只需要一步就可将掷骰子问题转化为抛硬币问题。how ?
抛出的点数为奇数,也即{1, 3, 5}为1,概率为1/2;
抛出的点数为偶数,也即{2, 4, 6}为0,概率为1/2;
如此便将掷骰子问题转换为了抛硬币问题。
以任一概率执行某一动作
某一概率
P
执行某一动作,在(0, 1)区间均匀分布上进行采样,也即
import scipy.stats as st
p = .6
u = st.uniform(0, 1)
if u.rvs() < p:
...
非均匀硬币:如何产生均匀的概率分布
就以普通的一元人民币硬币为例,正面为1字,反面为花,事实上,重心是稍微偏向反面的,此时如果想保证公平,应该如何指定。根据前面的描述,这道题目的答案应该十分简单了。正反:为正,反正:为反。
import random
from collections import Counter
def unfair_coin(p):
return 1 if random.random() < p else 0
def toss(p):
while True:
a, b = unfair_coin(p), unfair_coin(p)
if a - b == 1:
return 1
if b - a == 1:
return 0
if __name__ == '__main__':
N, p = 10000, 0.49
c = Counter((toss(p) for _ in range(N)))