【问题标题】:Python int too large to convert to CPython int 太大而无法转换为 C
【发布时间】:2021-04-25 16:48:47
【问题描述】:

我正在运行一段简单的代码来返回batch02**63 之间的整数个数(无需替换)。

from random import sample

batch = 1000
n = 63
rand_nos = sample(range(2**n), batch)

我得到了错误

Python int too large to convert to C ssize_t

我认为这与 random.sample 函数在内部将范围的长度转换为 int 值有关。但是我找不到任何可以设置的参数,以要求函数使用更大范围的数据类型。我该怎么办?谢谢。

【问题讨论】:

  • 那些是相当大的随机数。你用它们做什么?
  • 我宁愿相信由 numpy 引起的异常
  • @MitchWheat 我正在研究编码理论并且必须处理大型代码。这是我正在处理的代码的维度。
  • len(range(2**63))可以转载
  • @learner,检查range() 中的docs“允许包含大于sys.maxsize 的绝对值的范围,但某些功能(例如len())可能会引发OverflowError 。”

标签: python python-3.x random sample integer-overflow


【解决方案1】:

好的,您可以尝试使用Linear Congruential Generator,它有一些有趣的属性 - 选择好的常量,它将覆盖整个范围 [0...2n) 一次,而无需重复达到它的时期。因此,基本上相当于无放回抽样。

n=64 的代码,如果你正好需要 63,我可以挖出一组常数,问吧。

Python 3.9.1,Win10 x64

import numpy as np

class LCG(object):

    UZERO: np.uint64 = np.uint64(0)
    UONE : np.uint64 = np.uint64(1)

    def __init__(self, seed: np.uint64, a: np.uint64, c: np.uint64) -> None:
        self._seed: np.uint64 = np.uint64(seed)
        self._a   : np.uint64 = np.uint64(a)
        self._c   : np.uint64 = np.uint64(c)

    def next(self) -> np.uint64:
        self._seed = self._a * self._seed + self._c
        return self._seed

    def seed(self) -> np.uint64:
        return self._seed

    def set_seed(self, seed: np.uint64) -> np.uint64:
        self._seed = seed

    def skip(self, ns: np.int64) -> None:
        """
        Signed argument - skip forward as well as backward

        The algorithm here to determine the parameters used to skip ahead is
        described in the paper F. Brown, "Random Number Generation with Arbitrary Stride,"
        Trans. Am. Nucl. Soc. (Nov. 1994). This algorithm is able to skip ahead in
        O(log2(N)) operations instead of O(N). It computes parameters
        A and C which can then be used to find x_N = A*x_0 + C mod 2^M.
        """

        nskip: np.uint64 = np.uint64(ns)

        a: np.uint64 = self._a
        c: np.uint64 = self._c

        a_next: np.uint64 = LCG.UONE
        c_next: np.uint64 = LCG.UZERO

        while nskip > LCG.UZERO:
            if (nskip & LCG.UONE) != LCG.UZERO:
                a_next = a_next * a
                c_next = c_next * a + c

            c = (a + LCG.UONE) * c
            a = a * a

            nskip = nskip >> LCG.UONE

        self._seed = a_next * self._seed + c_next


#%%
np.seterr(over='ignore')

seed = np.uint64(1)

rng64 = LCG(seed, np.uint64(6364136223846793005), np.uint64(1))

print(rng64.next())
print(rng64.next())
print(rng64.next())

#%%
rng64.skip(-3) # back by 3
print(rng64.next())
print(rng64.next())
print(rng64.next())

rng64.skip(-3) # back by 3
rng64.skip(2) # forward by 2
print(rng64.next())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 2016-01-09
    • 2018-06-16
    • 2021-01-22
    相关资源
    最近更新 更多