内部随机整数概率(Python)

时间:2014-07-30 01:26:39

标签: python random range probability

我正在制作一个基于文本的RPG。我有一个算法可以确定玩家对敌人造成的伤害,该伤害是基于两个变量的值。我不确定算法的第一部分是如何工作的,但这并不重要。

AttackStrength是玩家的一个属性,通常表示他的攻击有多强。WeaponStrength是玩家挥动的剑的属性,通常代表武器对攻击的强烈程度。)< / p>

以下是算法的用法:

import random
Damage = AttackStrength (Do some math operation to WeaponStrength) WeaponStrength
DamageDealt = randrange(DamageDealt - 4, DamageDealt + 1) #Bad pseudocode, sorry

我要对最后一行做的是在整数范围内得到一个随机整数,其最小界限比伤害小4,并且最大界限比伤害大1。但是,这还不是全部。我想分配以下概率:

  • X%的时间DamageDealt将等于伤害
  • Y%的时间DamageDealt将等于一个小于伤害
  • Z%的时间DamageDealt将等于两个小于伤害
  • %Damage损失等于三等于损坏
  • B%的时间DamageDealt将等于三倍于伤害
  • C%的时间DamageDealt将等于一次伤害

我希望我没有过分复杂这一切,谢谢你!

4 个答案:

答案 0 :(得分:1)

我认为当你有一个很好的整数概率时,做随机加权概率的最简单方法就是简单地用你选择的多个副本填充一个列表 - 以正确的比例 - 然后随机选择一个元素。

让你的(原始)权重为10,10,25,25,30%,从-3到1。这些共享5的gcd,因此您只需要一个长度为20的列表来保留您的选择:

choices = [-3]*2 + [-2]*2 + [-1]*5 + [0]*5 + [1]*6

完成实施,只需从中随机选择即可。演示显示100个试验:

trials = [random.choice(choices) for _ in range(100)]

[trials.count(i) for i in range(-3,2)]
Out[18]: [11, 7, 27, 22, 33]

答案 1 :(得分:0)

基本上,你要完成的是模拟加载的模具:你有六种可能性,并希望为每个模具分配不同的概率。从数学上讲,这是一个相当有趣的问题,here是关于这一主题的精彩内容。

尽管如此,你可能还在寻找一些不那么冗长的东西,而这里最简单的模式是通过轮盘选择。给出一个字典,其中键是各种各样的方面&#39; (在这种情况下,你可能的损坏公式)和值是每一方可能发生的概率(.3, .25等),方法如下:

def weighted_random_choice(choices):
    max = sum(choices.values())
    pick = random.uniform(0, max)
    current = 0
    for key, value in choices.items():
        current += value
        if current > pick:
            return key

答案 2 :(得分:0)

假设我们想要为结果设置这些相对权重:

a = (10, 15, 15, 25, 25, 30)

然后我们创建一个部分和b和一个函数c的列表:

import random
b = [sum(a[:i+1]) for i,x in enumerate(a)]
def c():
    n = random.randrange(sum(a))
    for i, v in enumerate(b):_
        if n < v: return i

函数c将返回从0len(a)-1的整数,其概率与a中指定的权重成比例。

答案 3 :(得分:0)

这可能是一个棘手的问题,有很多不同的概率。既然你想对结果施加概率,那么将它们称为“随机”并不公平。想象一下如何表示数据总是有帮助的。一种方法是保持元组的元组,如

probs = ((10, +1), (30, 0), (25, -1), (25, -2), (15, -3))

您会注意到我已经调整了系列以首先进行最高调整,依此类推。我还删除了你的问题暗示的副本“15,-3”,因为(我想)一条线是偶然重复的。一个非常有用的测试是确保你的概率加起来为100(因为我把它们表示为整数百分比)。这揭示了数据错误:

>>> sum(prob[0] for prob in probs)
105

除非您真的希望自己的概率达到合理的值,否则这不一定是个问题。如果没有必要,您可以将它们视为加权并从(0,104)而不是(0,99)中选择随机数。这是我将遵循的课程,但调整应该相对简单。

给定probs以及介于0和(在您的情况下)104之间的随机数,您可以迭代probs结构,累积概率,直到找到此特定随机数所属的bin。这看起来像(像):

def damage_offset(N):
    prob = random.randint(0, N-1)
    cum_prob = 0
    for prob, offset in probs:
        cum_prob += prob
        if cum_prob >= prob:
            return offset

如果你的数据是正确的,那么这应该总是终止(因此我的偏执检查你的权重 - 我已经做了很长时间了。)

当然,通常可以交换内存以提高速度。如果上述需要更快地工作,那么创建一个将随机整数选择直接映射到结果的结构相对容易。构建这种映射的一种方法是

damage_offsets = []
for i in range(N):
    damage_offsets.append(damage_offset(i))

然后,在您从1到N之间选择随机数r之后,您需要做的就是查找damage_offsets[r-1]以查找r1的特定值并创建了一个O(1)操作。正如我在开始时提到的,除非你的概率列表变得很大,否则这可能不会非常有用(但如果确实如此,那么当你有大N的N时,你真的需要避免O(N)操作。概率桶)。

为未经测试的代码道歉。