问题
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