我想让Python 3.7.1选择一个0到100之间的数字。但是我想要一个更低的数字,而不是更高的数字,以反向指数 - 平滑 - 毕业 - 曲线的方式(没有确切地说)。
我想我可以先说
myrandomnumber = random.randint(0, 100)
然后将其链接到某种数组,以确定每个数字的不同百分比。我见过其他人用随机掷骰子来做这件事,但问题是,这只有六种可能性非常整齐,我想这样做一百(或更多)并且不想坐在那里做一个巨大的只有一百个条目的数组。当然我可以这样做,我想,但我觉得Python可能有一个非常简单的方法来做到这一点,我错过了。
谢谢,伙计们!
你可能想要的是一个gamma分布式随机数。
例如,使用k=1
和θ=2.0
:
有使用均匀分布的random
函数生成normal
,exponential
或gamma
分布值的算法。
但是因为你在python中,你可能会直接使用numpy的random.gamma
函数:
#the (1,2) shape ends basically at 20. Multiply by 5 to get my 0..100 scale
numpy.random.gamma(1, 2.0) * 5
我假设您想要在有界范围内生成整数值,并且当您谈论“偏差”时,您的意思是非均匀分布。由于您没有考虑特定的参数分布,因此一种方法是从连续分布开始,并使用int()
获取结果的“底限”。您需要将上限增加1,以便向下舍入给出包含该边界的值。
一个简单的选择是triangular distribution。 Python提供random.triangular()
函数,它接受3个参数 - 下限,上限和模式。这是一个离散版本:
import random as rnd
import math
import sys
def triangle(upper_bound):
return int(rnd.triangular(0.0, float(upper_bound + 1) - sys.float_info.epsilon, 0.0))
我从上限减去了浮动的epsilon,以防止在你的上限为100时获得101的结果的可能性(极不可能)。另一个有限的分布选择可能是beta distribution,然后你可以缩放和截断。
如果你希望分布向下移动到0,那么你可以使用exponential等分布,或者更常见的是gamma,使用截断和舍入。这两者都有无限支持,因此有两种方法可以截断。更简单的方法是使用acceptance/rejection-keep生成值,直到你得到一个范围:
def expo_w_rejection(upper_bound, scale_param = 0.4):
upper_bound += 1
while True:
candidate = rnd.expovariate(1.0 / (upper_bound * scale_param))
if candidate < upper_bound:
return int(candidate)
和以前一样,将上限提高1,以获得包含截断后上限的结果。我还包括一个可选的scale_param
,它应该是一个严格在0和1之间的值,即不包括任何一个限制。接近0的值将导致结果向左移动更多,接近1的值产生更少的聚束。
另一种方法是使用逆变换技术生成,并基于评估目标上限处的累积分布函数来限制均匀范围不超过上限:
def trunc_exp(upper_bound, scale_param = 0.4):
upper_bound = float(upper_bound) + 1.0 - sys.float_info.epsilon
trunc = 1.0 - math.exp(-1.0 / scale_param)
return int((-upper_bound * scale_param) * math.log(1.0 - trunc * rnd.random()))
两种方法都产生分布式模拟结果,如下面的屏幕截图所示。产生“第1列”并进行截断反转,而“第2列”产生接受/排斥。