我需要根据二项分布随机生成一系列数字。 Numpy的随机套件提供了一种方法来实现这一点,但遗憾的是它似乎仅限于处理 n 值的32位数字,我想处理该范围之外的值。 64位应该足够了,尽管任意更高的精度也可以正常工作。
示例输出:
>>> np.random.binomial(1<<40, 0.5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "mtrand.pyx", line 3506, in mtrand.RandomState.binomial (numpy\random\mtrand\mtrand.c:16555)
OverflowError: Python int too large to convert to C long
我可以使用替代品吗?或者这种随机生成器内部使用64位数字的方法是什么?
或者我是否需要自己兜售?
(正如Robert Klein指出的那样,除了Windows之外,numpy在64位平台上做了64位;不幸的是我使用的是Windows)。
答案 0 :(得分:2)
在C long
整数为64位的机器上,numpy.random.binomial()
将接受并生成64位整数。除Windows之外的大多数64位平台都是这样。例如,在我的64位OS X机器上:
[~]
|11> np.random.binomial(1 << 40, 0.5)
549755265539
[~]
|12> np.random.binomial(1 << 40, 0.5) > (1<<32)
True
或者,如果您遇到Windows,请考虑将Normal Approximation用于二项分布。如此大的n
,近似值应该非常好。
def approx_binomial(n, p, size=None):
gaussian = np.random.normal(n*p, n*p*(1-p), size=size)
# Add the continuity correction to sample at the midpoint of each integral bin.
gaussian += 0.5
if size is not None:
binomial = gaussian.astype(np.int64)
else:
# scalar
binomial = int(gaussian)
return binomial
答案 1 :(得分:1)
有一个精确有效的采样器可以生成二项式( n ,1/2)随机变量,即使 n 很大,如Bringmann等人所述。 2014。与该论文中描述的算法等效的算法如下:
(请注意,Bringmann论文的算法比此算法更复杂,部分是为了避免由于精度有限而导致的舍入误差,Farach-Colton和Tsai [2015]展示了如何对二项式( n < / em>, p )任意 p 的随机变量可以简化为抽样二项式( n ,1/2)变量的问题。有关更多详细信息,请参阅这些论文或我的笔记“ On a Binomial Sampler”。)
以下是二项(1/2)算法的纯Python实现,它不依赖底层操作系统的32位/ 64位支持。
import random
import math
def binomhalf(n):
if n<4: return sum(random.randint(0,1) for i in range(n))
if n%2==1: return random.randint(0,1)+binomhalf(n-1)
m=int(math.sqrt(n))+1
while True:
k=0
while random.randint(0,1)==0: k+=1
i=k*m+random.randint(0,m-1)
ret=n//2+i if random.randint(0,1)==0 else n//2-i-1
if ret<0 or ret>n: continue
expo=-random.expovariate(1)
p=math.lgamma(n+1)-math.lgamma(ret+1)-math.lgamma((n-ret)+1)+ \
math.log(m)+math.log(2)*((k-n)+2)
if expo<=p: return ret
参考: