Python随机函数不使用随机模块 [英] Python Random Function without using random module

查看:180
本文介绍了Python随机函数不使用随机模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要编写函数 -

  random_number(最小值,最大值)

不使用随机模块,我这样做:

  b 
$ b def random_number(最小值,最大值):
now = str(time.clock())
rnd = float(now [:: - 1] [:3:])/ 1000
最低回报+ rnd *(最高 - 最低)

我不确定这是否正确..有没有一种已知的方法来做到这一点?

解决方案


事情是我需要做一些以某种方式使用时间的东西


您可以基于时钟漂移

 进口结构
进口时间

def lastbit(f):
返回struct.pack('!f',f)[ - 1]& 1

def getrandbits(k):
使用两个时钟的相对漂移返回k个随机位。
#假设time.sleep()和time.clock()使用不同的时钟
#,即使它们使用相同的时钟也可能工作
#XXX它不产生好随机有关详细信息,请参见以下内容:
结果= 0
for _范围(k):
time.sleep(0)
结果<= 1
结果| = lastbit(time.clock())
返回结果

code> getrandbits(k),在范围[a,b]中得到一个随机整数,包括两个端点是很直接的。 基于CPython Lib / random.py

  def randint(a,b):
返回范围[a,b]中的随机整数,包括两端点。
return a + randbelow(b - a + 1)

def randbelow(n):
返回范围[0,n)的随机int。 N'LT = 0。
#from Lib / random.py
if n <= 0:
raise ValueError
k = n.bit_length()#不要在这里使用(n-1) n可以是1
r = getrandbits(k)#0≤r< 2 ** k
而r> = n:#避免歪斜
r = getrandbits(k)
返回r

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

  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



random bits然后 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(写):
而真:
写(getrandbits(32).to_bytes(4,'big'))

if __name__ == __main__:
import sys
write_random_binary_stream(sys.stdout.buffer.write)

>上面假设你不允许使用 os.urandom() ssl.RAND_bytes(),或者一些已知的PRNG算法,如 Mersenne Twister 实现 getrandbits(k)






getrandbits(n)使用 time.sleep() + time.clock()实现失败 dieh arder 测试(太多是巧合)。

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


I need to write the function -

random_number(minimum,maximum)

Without using the random module and I did this:

import time

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

I am not sure this is fine.. is there a known way to do it with the time?

解决方案

The thing is I need to do something that somehow uses the time

You could generate randomness based on a 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

Once you have getrandbits(k), it is straigforward to get a random integer in range [a, b], including both end points. 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

Example, to generate 20 random numbers from 10 to 110 including:

print(*[randint(10, 110) for _ in range(20)])

Output:

11 76 66 58 107 102 73 81 16 58 43 107 108 98 17 58 18 107 107 77

If getrandbits(k) returns k random bits then randint(a, b) should work as is (no skew due to modulo, etc).

To test the quality of getrandbits(k), dieharder utility could be used:

$ python3 random-from-time.py | dieharder -a -g 200

where random-from-time.py generates infinite (random) binary stream:

#!/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)

where getrandbits(k) is defined above.


The above assumes that you are not allowed to use os.urandom() or ssl.RAND_bytes(), or some known PRNG algorithm such as Mersenne Twister to implement getrandbits(k).


getrandbits(n) implemented using "time.sleep() + time.clock()" fails dieharder tests (too many to be a coincidence).

The idea is still sound: a clock drift may be used as a source of randomness (entropy) but you can't use it directly (the distribution is not uniform and/or some bits are dependent); the bits could be passed as a seed to a PRNG that accepts an arbitrary entropy source instead. See "Mixing" section.

这篇关于Python随机函数不使用随机模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆