这是Python cookbook的示例
1 def random_pick(some_list,probabilities):
2 x=random.uniform(0,1)
3 cumulative_probability=0.0
4 for item,item_probability in zip(some_list,probabilities):
5 cumulative_probability+=item_probability
6 if x < cumulative_probability: break
7 return item
什么意思呢?
random.uniform(0,1)->生成0.0到1.0之间的伪随机数,之后循环元素及其概率,计算累积概率.
如:random_pick([1,2,3,4],[0.1,0.2,0.3,0.4])
当x处于0.0到0.1之间,则输出1
当x处于0.1到0.3之间,则输出2
...........
在这里可以做个测试:
def test_random(nu):
a=[1,2,3,4]
b=[0.1,0.2,0.3,0.4]
re=dict(zip(a,[0]*4))
for x in xrange(nu):
result=random_pick(a,b)
re[result]+=1
for v,value in re.iteritems():
re[v]=float(value)/nu
return re
print test_random(100000)
结果:
{ 1 : 0.099250000000000005 , 2 : 0.19950999999999999 , 3 : 0.30030000000000001 , 4 : 0.40094000000000002 } |
另一个有点类似的任务是根据一个非负整数的序列所定义的权重进行随机撷取---基于机会,而不是概率
import random
def random_picks(sequence,relative_odds):
table=[z for x,y in zip(sequence,relative_odds) for z in [x]*y]
while True:
yield random.choice(table)
x=random_picks('ciao',[1,1,3,2])
import itertools
print ''.join(itertools.islice(x,8))
输出:
oooocaco |
这里我们也做个测试:
result=''.join(itertools.islice(x,100000))
c=result.count('c')
i=result.count('i')
a=result.count('a')
o=result.count('o')
min=min(c,i,a,o)
print float(c)/min,':',float(i)/min,':',float(a)/min,':',float(o)/min
输出:
1.0 : 1.0210748156 : 3.00316122234 : 2.00070249385 |
这两个例子有什么区别呢?
第一个例子要求som_list的长度和probabilities的长度一致,以及所有元素的概率相加为1.0
而第二个例子需要非负整数.