【问题标题】:Easiest way to generate random int64 array in numpy?在 numpy 中生成随机 int64 数组的最简单方法?
【发布时间】:2016-04-22 15:09:13
【问题描述】:

我想让int64 的随机数组均匀分布在int32 限制之外的某个范围内。

randintrandom_integers 但它们与int32 一起使用;提供较大的上限会产生high is out of bounds for int32

如何生成指定范围的随机int64 数组?

可能的解决方案:

  • 使用浮动生成器。在这种情况下它的分辨率不会很差吗?
  • 生成随机字节,将它们解释为int64 数组,然后通过lower + x % (upper - lower) 标准化。但是int32 代是否具有相同的规范化?不影响均匀度吗?

我是不是错过了一些更简洁方便的方式?

为什么随机方法只产生floats 和int32

【问题讨论】:

标签: python numpy random


【解决方案1】:

编辑:

在 numpy > 1.11.0 的 Windows 上使用 dtype:

根据 @John Y 的建议,似乎可以使用 dtype 作为命名参数和 np.random.randint 将整数转换为所需的格式:

a = np.random.randint(2147483647, 9223372036854775807, size=3, dtype=np.int64)

[结束编辑]

可以通过设置randint的范围直接生成数组;它可能比数组的零碎生成和聚合更有效:

文档字符串: (numpy randint)

randint(low, high=None, size=None)

如果 int 32 的大小范围:

ii32 = np.iinfo(np.int32)
iinfo(min=-2147483648, max=2147483647, dtype=int32)

int64 的大小范围 c long

ii64 =  np.iinfo(np.int64)
iinfo(min=-9223372036854775808, max=9223372036854775807, dtype=int64)

生成 val > int32.max 的 int64 数组:

a = np.random.randint(2147483647, 9223372036854775807, size = 3)
array([4841796342900989982,   43877033468085758,  205656391264979944])

检查数据类型:按预期给出int64

a.dtype
dtype('int64')


numpy.randint 在指定范围内为您提供均匀分布(注意,该范围不包括两端,与 python randint 不同)

【讨论】:

  • 我只是尝试了完全相同的方法并得到了high is out of bounds for int32。我的配置是 Windows 7 64 位,Python 3.4.3 32 位,numpy 1.11.0。
  • 嗯...很遗憾,我无法帮助您,我没有 Windows 机器,而且我的设置是 python 64 位。 (这可以解释它为什么起作用)
  • 我会在 Linux 和 Windows 上的 64 位 Python 上检查它。
  • 您可能必须将dtype 参数显式指定为(NumPy 的)randint()。在我的系统上,如果我没有指定它,我会得到ValueError: high is out of bounds for int32。但是a = np.random.randint(2147483647, 9223372036854775807, size=3, dtype=np.int64) 有效。显然,这个参数还没有进入官方文档;该功能是最近才添加的(我认为是 2016 年 1 月)。
  • 这是一个很好的建议 John Y。有趣的是,dtype 会在 Mac osx 上使用 python 64 抛出:TypeError: randint() got an unexpected keyword argument 'dtype'。你在 Windows 机器上吗?也许这是为克服 windows int32 而实施的解决方法 numpy?
【解决方案2】:

正如 Robert Kern 在上面的 cmets 中已经提到的,在 numpy (v1.11.0) 的最新版本中np.random.randint accepts a dtype= parameter which allows you to generate 64-bit integers directly

如果你有一个旧版本的 numpy 并且由于某种原因你不能升级,你建议的生成随机字节的解决方案,将它们视为 int64 并根据你想要的范围截断它们应该同样有效 - in事实上,that's essentially how numpy's internal RNG does it*.

*正如 @moarningsun 在下面指出的rk_random_uint64 实际上使用拒绝采样,但我仍然认为没有理由不使用模数包装这些值。

import numpy as np
from scipy import stats

def randint64(low, high, size, seed=None):

    # generate a string of random bytes
    n = np.prod(size)
    bytes = np.random.RandomState(seed).bytes(n * 8)

    # view as an int64 array
    ints = np.fromstring(bytes, np.int64, n).reshape(size)

    ints %= np.int64(high - low)    # truncate
    ints += np.int64(low)           # offset

    return ints

imax = np.iinfo(np.int64).max
print(imax)
# 9223372036854775807

ints = randint64(0, imax, int(1E6), seed=0)

print(ints.max())
# 9223355891497906972

# test uniformity
print(stats.kstest(ints, stats.uniform(loc=0, scale=imax).cdf))
# KstestResult(statistic=0.00085961807556278469, pvalue=0.45082598256836681

【讨论】:

  • 在那个 Numpy 代码中,超出范围的值将被丢弃,而不是环绕!我认为评论“如果 rng 足够大,数字换行”指的是无符号添加 out[i] = off + val;
【解决方案3】:

您可以使用random.randint并转换返回值:

>>> import numpy as np
>>> import random
>>> np.int64(random.randint(10000, 1000000000000))
321601597066

我不能保证这是最快的方法,但至少它有效并且非常清晰......(并且要获得一个数组,你只需这样做一堆次)。

【讨论】:

  • 确实,应该可以。我必须测试它的效率。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
相关资源
最近更新 更多