How to generate 8 bytes unique random number in python?

戏子无情 提交于 2021-01-28 06:06:32

问题


Is there any way to generate a unique random number that has 8 bytes size in python language? I used the UUID library but it has 16 bytes which are not aligned with my requirement.

Any help would be much appreciated.

Thanks in advance


回答1:


Well, you could use Linear Congruential Generator which, with proper selection of parameters, produce perfect mapping from u64 to u64. In other words, if you have access to previous 8bytes UUID, you could generate reasonable random next 8bytes UUID WITHOUT REPETITIONS till whole 264 space ix exhausted. It could also go backward and forward N steps in O(log(N)).

Code using NumPy, Python 3.7, Anaconda, Win 10 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')

a = np.uint64(6364136223846793005)
c = np.uint64(1)

seed = np.uint64(1)

rng64 = LCG(seed, a, c)

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())



回答2:


In Python 3.6 and later, this is easy:

  • Import the secrets module: import secrets.
  • Generate a random byte sequence with secrets.token_bytes(8). Or, if the string should be readable, use the following which produces a 16-character string out of 8 bytes (secrets.token_hex(8)), or an 8-character string out of 4 bytes (secrets.token_hex(4)).


来源:https://stackoverflow.com/questions/62797012/how-to-generate-8-bytes-unique-random-number-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!