Python int 太大,无法转换为 C

lea*_*ner 5 python random sample integer-overflow python-3.x

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

from random import sample

batch = 1000
n = 63
rand_nos = sample(range(2**n), batch)
Run Code Online (Sandbox Code Playgroud)

我收到错误

Python int too large to convert to C ssize_t
Run Code Online (Sandbox Code Playgroud)

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

Sev*_*eux 0

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

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())
Run Code Online (Sandbox Code Playgroud)