不使用随机模块的Python随机函数

ori*_*ari 1 python random time function

我需要编写函数-

random_number(minimum,maximum)
Run Code Online (Sandbox Code Playgroud)

在不使用随机模块的情况下,我这样做:

import time

def random_number(minimum,maximum):
    now = str(time.clock())
    rnd = float(now[::-1][:3:])/1000
    return minimum + rnd*(maximum-minimum)
Run Code Online (Sandbox Code Playgroud)

我不确定这是否可以..是否有已知的方法来解决这个问题?

jfs*_*jfs 5

事情是我需要做一些花费时间的事情

您可以根据时钟漂移生成随机性:

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

一旦有了getrandbits(k),就可以得到[a,b]范围内的一个随机整数,包括两个端点。基于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
Run Code Online (Sandbox Code Playgroud)

例如,要生成从10到110的20个随机数,包括:

print(*[randint(10, 110) for _ in range(20)])
Run Code Online (Sandbox Code Playgroud)

输出:

11 76 66 58 107 102 73 81 16 58 43 107 108 98 17 58 18 107 107 77
Run Code Online (Sandbox Code Playgroud)

如果getrandbits(k)返回k随机位,则randint(a, b)应按原样工作(不会因模等引起偏斜)。

要测试的质量getrandbits(k)dieharder可以使用实用程序:

$ python3 random-from-time.py | dieharder -a -g 200
Run Code Online (Sandbox Code Playgroud)

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

其中getrandbits(k)以上定义。


上面的假设假定您不允许使用os.urandom()ssl.RAND_bytes()或某些已知的PRNG算法(例如 Mersenne Twister)来实现getrandbits(k)


getrandbits(n)使用“ time.sleep()+ time.clock()” 实现的dieharder测试失败(太多是巧合)。

这个想法仍然是正确的:时钟漂移可能被用作随机性(熵)的来源,但是您不能直接使用它(分布不均匀和/或某些位是相关的);这些位可以作为种子传递给PRNG,而PRNG可以接受任意熵源。请参阅“混合”部分