我有一些随机结果,我想模拟随机结果。
outcomes_mapping = {0.10:"Outcome A", 0.60:"Outcome B", 0.30:"Outcome C"}
结果A应在10%的时间内发生,结果B应在60%的时间内,结果C应在30%的时间内。
目前,我的解决方案是这样的:
def random_encounter():
roll = np.random.rand()
if roll <= 0.1:
return "Outcome A"
if roll > 0.1 and roll <=0.6:
return "Outcome B"
有什么更聪明的方法可以做到这一点吗?我的解决方案显然涉及大量的硬编码。我应该使用累积概率吗?即使我这样做了,我的函数仍然是if roll > 0.1, return this, else return that
格式。如果可能的话,我想维护一个主"结果映射"字典,我可以在我的功能中参考它。
您可以在random.choices
:中使用weights
参数
from collections import Counter
import random
outcomes_mapping = {0.10:"Outcome A", 0.60:"Outcome B", 0.30:"Outcome C"}
c = Counter()
for i in range(1000):
c.update( random.choices([*outcomes_mapping.values()], weights=outcomes_mapping.keys()) )
print(c)
打印:
Counter({'Outcome B': 596, 'Outcome C': 317, 'Outcome A': 87})
我对此的看法是,当结果的映射看起来像这样时,键对每种可能性都有下限和上限:
mapping = {(0.0, 0.1) : "A", (0.1, 1) : "B"}
def roll(mapping, roll):
for limit, val in mapping.items():
if limit[0] < roll <= limit[1]:
return val
输出:
roll(mapping, 0.1)
'A'
roll(mapping, 0.2)
'B'
根据您想要的范围以及滚动的输入值,您可以使用稍微更改的映射(例如0.0
到-0.1
(或其他范围检查。
因为您已经有了一个包含值的字典,所以您可以执行类似的操作
cumulative = 0
for k in outcomes_mapping:
cumulative += k
if roll <= cumulative:
return outcomes_mapping[k]
这样,您只需要在更改或添加值时更新字典。
您需要保持cumulative
计数的原因是您的地图包含绝对概率:结果B将在60%的时间内显示,但这是滚动范围"0.1
到0.7
",因此我们需要将结果A的10%相加(感谢您指出@marcus.aurelianus(。