31

我需要根据加权循环返回不同的值,这样 20 人中有 1 人获得 A,20 人中有 1 人获得 B,其余的人获得 C。

所以:

A => 5%
B => 5%
C => 90%

这是一个似乎可以工作的基本版本:

import random

x = random.randint(1, 100)

if x <= 5:
    return 'A'
elif x > 5 and x <= 10:
    return 'B'
else:
    return 'C'

这个算法正确吗?如果是这样,是否可以改进?

4

4 回答 4

60

你的算法是正确的,更优雅的东西怎么样:

import random
my_list = ['A'] * 5 + ['B'] * 5 + ['C'] * 90
random.choice(my_list)
于 2013-02-21T00:42:37.123 回答
37

没关系。更一般地说,您可以定义如下内容:

from collections import Counter
from random import randint

def weighted_random(pairs):
    total = sum(pair[0] for pair in pairs)
    r = randint(1, total)
    for (weight, value) in pairs:
        r -= weight
        if r <= 0: return value

results = Counter(weighted_random([(1,'a'),(1,'b'),(18,'c')])
                  for _ in range(20000))
print(results)

这使

Counter({'c': 17954, 'b': 1039, 'a': 1007})

与您预期的一样接近 18:1:1。

于 2013-02-21T00:38:11.437 回答
9

如果您想使用加权随机而不是百分位随机,您可以创建自己的 Randomizer 类:

import random

class WeightedRandomizer:
    def __init__ (self, weights):
        self.__max = .0
        self.__weights = []
        for value, weight in weights.items ():
            self.__max += weight
            self.__weights.append ( (self.__max, value) )

    def random (self):
        r = random.random () * self.__max
        for ceil, value in self.__weights:
            if ceil > r: return value

w = {'A': 1.0, 'B': 1.0, 'C': 18.0}
#or w = {'A': 5, 'B': 5, 'C': 90}
#or w = {'A': 1.0/18, 'B': 1.0/18, 'C': 1.0}
#or or or

wr = WeightedRandomizer (w)

results = {'A': 0, 'B': 0, 'C': 0}
for i in range (10000):
    results [wr.random () ] += 1

print ('After 10000 rounds the distribution is:')
print (results)
于 2013-02-21T02:35:31.297 回答
0

这似乎是正确的,因为您使用的是uniform具有独立抽签的随机变量,每个数字的概率将为1/n (n = 100)。

您可以通过运行 1000 次并查看每个字母的频率来轻松验证您的算法。

您可能考虑的另一种算法是在给定每个字母所需的频率的情况下生成一个包含字母的数组,并且只生成一个随机数,该随机数是数组中的索引

它在内存中的效率会降低,但性能应该会更好

编辑:

为了回应@Joel Cornett 的评论,一个示例将与@jurgenreza 非常相似,但内存效率更高

import random
data_list = ['A'] + ['B'] + ['C'] * 18
random.choice(data_list )
于 2013-02-21T00:38:39.477 回答