Python 可替代允许64位或更多位的numpy.random.binomial?

Python 可替代允许64位或更多位的numpy.random.binomial?,python,python-3.x,numpy,random,Python,Python 3.x,Numpy,Random,我需要根据二项分布随机生成一系列数字。Numpy的随机套件提供了一种实现这一点的方法,但不幸的是,它似乎仅限于处理n值的32位数字,我希望处理该范围以外的值。64位应该足够了,尽管任意更高的精度也可以 示例输出: >>> np.random.binomial(1<<40, 0.5) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "

我需要根据二项分布随机生成一系列数字。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

>>np.random.binomial(1在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

Bringmann et al.2014中描述了一种精确有效的采样器,用于生成二项式(n,1/2)随机变量,即使n很大。与本文中描述的算法等效的算法如下:

  • 如果n小于4,则生成n个无偏随机位(0或1)并返回其和。否则,如果n为奇数,则将ret设置为该算法的结果,且n=n− 1,然后将无偏随机位的值添加到ret,然后返回ret
  • 将m设置为地面(sqrt(n))+1
  • (首先,从二项式曲线的包络中采样。)生成无偏随机位(零或一),直到以这种方式生成零。将k设置为以这种方式生成的一个数
  • 将s设置为均匀随机选择的[0,m]中的整数,然后将i设置为k*m+s
  • 将ret设置为n/2+i或n/2− 我− 1的概率相等
  • (第二,接受或拒绝ret。)如果ret<0或ret>n,则转至步骤3
  • 概率选择(n,ret)*m*2(k)− n) +2,返回ret。否则,转到步骤3。(这里,choose(n,k)是一个二项式系数。下面的Python代码计算这个概率的对数。)
  • (注意,布林格曼论文的算法比这更复杂,部分原因是为了避免精度有限导致的舍入误差,Farach Colton和Tsai[2015]展示了如何将任何p的二项(n,p)随机变量抽样问题简化为二项(n,1/2)抽样问题。)变量。有关更多详细信息,请参阅那些论文或我的笔记。“)

    下面是二项式(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
    
    随机导入
    输入数学
    def binomhalf(n):
    
    如果NCAN能更详细地解释这一点吗?<代码> NP.Actudio。二项式(NP.IINFO(NP.IN64)。max,0.5)< /C> >在我的LAPTOP上是很好的。有趣的是,我使用Windows,所以它没有多大帮助。考虑使用二项式分布。它可能在这样的大的<代码> N< /代码>中有更好的行为。<代码> NP.Realth.Read。(n*p,np.sqrt(n*p*(1-p)).astype(np.int64)
    你能把它作为一个答案发布出来,这样我就可以接受了吗?把它添加到这个答案中。谢谢!我添加了一个连续性更正,发现我需要以正常的方式转换为int,而不是使用
    .astype
    ,但在其他方面效果很好。谢谢,罗伯特。
    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