Дело в том, что мне нужно сделать что-то, что каким-то образом использует время
Вы могли бы генерировать хаотичность на основе clock drift:
import struct
import time
def lastbit(f):
return struct.pack('!f', f)[-1] & 1
def getrandbits(k):
"Return k random bits using a relative drift of two clocks."
# assume time.sleep() and time.clock() use different clocks
# though it might work even if they use the same clock
#XXX it does not produce "good" random bits, see below for details
result = 0
for _ in range(k):
time.sleep(0)
result <<= 1
result |= lastbit(time.clock())
return result
После того как вы getrandbits(k)
, это для получения случайного целого в диапазоне [a, b], включая обе конечные точки. Based on CPython Lib/random.py:
def randint(a, b):
"Return random integer in range [a, b], including both end points."
return a + randbelow(b - a + 1)
def randbelow(n):
"Return a random int in the range [0,n). Raises ValueError if n<=0."
# from Lib/random.py
if n <= 0:
raise ValueError
k = n.bit_length() # don't use (n-1) here because n can be 1
r = getrandbits(k) # 0 <= r < 2**k
while r >= n: # avoid skew
r = getrandbits(k)
return r
Пример, чтобы генерировать 20 случайных чисел от 10 до 110 в том числе:
print(*[randint(10, 110) for _ in range(20)])
Выход:
11 76 66 58 107 102 73 81 16 58 43 107 108 98 17 58 18 107 107 77
, если getrandbits(k)
возвращает k
случайные биты, то randint(a, b)
должен работать как (без перекоса по модулю и т. д.).
Чтобы проверить качество getrandbits(k)
, может быть использована утилита dieharder
:
$ python3 random-from-time.py | dieharder -a -g 200
, где random-from-time.py
генерирует бесконечный (случайный) двоичный поток:
#!/usr/bin/env python3
def write_random_binary_stream(write):
while True:
write(getrandbits(32).to_bytes(4, 'big'))
if __name__ == "__main__":
import sys
write_random_binary_stream(sys.stdout.buffer.write)
, где getrandbits(k)
определен выше.
выше предполагает, что вы не можете использовать os.urandom()
или ssl.RAND_bytes()
, или какой-либо известный PRNG алгоритм, такой как Mersenne Twister реализовать getrandbits(k)
.
getrandbits(n)
реализован с использованием "time.sleep()
+ time.clock()
" терпит неудачу dieharder
испытания (слишком много, чтобы быть совпадением).
Идея по-прежнему звучит: дрейф часов может использоваться как источник случайности (энтропия), но вы не можете использовать его напрямую (распределение неравномерно и/или некоторые биты зависят); биты могут быть переданы как семя в PRNG, который вместо этого принимает произвольный источник энтропии. См. "Mixing" section.
Можете ли вы уточнить, что ваши требования находятся? Какие тесты случайности нужно пройти? Как написано, трудно понять, о чем вы спрашиваете. – BlackVegetable
Определите, что вы подразумеваете под случайным, для некоторых стандартных модульных «rand» недостаточно, а для некоторого 'return 4; // на основе справедливого броска кубика. – luk32
Попытка изображения этой функции должна быть как randrange, это достаточно хорошо? – oridm