Python加权范围内的随机数



我正在尝试编写一个函数,该函数将生成一个加权随机数。简单地说,我有两个范围,其中一个属于另一个范围。在x%的情况下,数字应该在内部范围内,但在y%中,它应该在外部范围外。

生成加权随机数我发现了这个关于加权随机数的问题,但这导致了一个从选项列表中选择的数字,而不是一个范围内的随机数。有可能这样做吗?

不过,这只是我实际问题的一部分,因为我还需要考虑之前生成的数字,并在该数字的一定范围内。如果这个范围在内部范围内,显然不会出现问题,但如果它与外部范围重叠,就会变得更加复杂。

我正试图用波动的数字构建一个模拟器,这些数字通常在"正常"范围内,但并不总是如此,因为它应该是随着时间的推移而演变的数据,所以下一个数字不能与上一个数字偏离太多。

编辑:我现在已经尝试过这样做,如果前一个数字的偏差在内部范围内,它将在该偏差范围内取一个"正常"随机数。如果偏差超过了两侧的内部范围,我会使用百分比来确定数字是否应该在范围内。如果没有,它将在外部范围内选择一个数字。当我决定偏差范围将小于内部范围时,它永远不会超过一侧的内部范围。这样就有可能像Patrick Gartner建议的那样进行设置。我实现它如下:

def RNG_with_ranges(r1, r2, chance, dev, prev):
if prev-dev >= r1[0] and prev+dev <= r1[1]:  # within inner range
return random.randint(prev-dev, prev+dev)  # normal random, I stick with ints for now
else:  # not entirely within inner range
p = random.random()
if p*100 <= chance:  # if we will get a number in the normal range
if prev+dev < r1[0]:  # if we are further left from the inner range than our dev allows
return r1[0]  # return to the border, but this should be improved
elif prev-dev > r1[1]:  # if we are further right from the inner range than our dev allows
return r1[1]  # return to the border, but this should be improved
return random.randint(max(r1[0], prev - dev), min(r1[1], prev + dev))
else:  # if we get an outer range value
if prev-dev < r1[0]:  # if we are left of the inner range
# take a number between the dev or outer range limit and the dev or inner range limit
return random.randint(max(prev-dev, r2[0]), min(prev+dev, r1[0]))
elif prev+dev > r1[1]:  # if we are right of the inner range
# take a number between the dev or outer range limit and the dev or inner range limit
return random.randint(max(prev-dev, r1[1]), min(prev+dev, r2[1]))

剩下的问题是,只有当我们到达内部和外部范围之间的边界时,百分比才会发挥作用,因此实际百分比将不可预测地低于给定的百分比。

当然,只需计算两次即可。我的实现在两个范围之间进行选择,我将的实现留给您,选择较小的内部或较大的外部,但不选择内部

import random
# this is a either/or implementation
def wrn(r1, r2, perc):
"""Takes two ranges (or other iterables) and an integer perc value. Draws a random
number from r1 if a random.randint(1,100) is below or equal perc, else draws the 
number from r2 and returns it."""
assert 1<=perc<=100, "perc must be in the range of [1,100]"
p = random.randint(1,100)

# choose which range to use
if p <= perc:
return random.choice(r1)
# to get something in the bigger range but not in the smaller included range
# you might need to reroll the bigger range number multiple times
# until your value is no longer in the smaller, included inner range
return random.choice(r2)

r1 = range(1,11)
r2 = range(10,100)
for _ in range(10):
print(wrn(r1,r2,50))

输出:

89   # r2
9    # r1
7
5
30   # r2
7    # r1
8
39   # r2
48
79

如果你不喜欢为你的版本重新绘制,你可以创建一个包含所有数字的列表:k = [[n for n in r1 if n not in r2],并绘制一次-只需确保你不会用类似range(1,10**20),range(2,3)的东西来称呼它-该列表是一个巨大的

最新更新