【问题标题】:Random int without importing 'random'不导入“随机”的随机整数
【发布时间】:2014-05-21 23:02:05
【问题描述】:

有没有办法让程序在不导入 random 的情况下选择 1 到 1,000 之间的随机数?

【问题讨论】:

  • 为什么不能只导入random?您可以开始编写自己的随机数生成代码,但您为什么要这样做?
  • 当然,只需编写您自己的 PRNG,或者从系统的(例如 /dev/random)中读取。
  • 当然有:xkcd.com/221(简单翻译成Python)。换句话说,如果您告诉我们您打算这样做,您更有可能得到有用的答案。

标签: python python-3.x random


【解决方案1】:

假设你想要整数。

import numpy as np
np.random.randint(1,1000)

【讨论】:

  • 嘿,我忘了说我不能导入任何东西。这是本次作业的规则之一。顺便说一句,这是家庭作业的一小部分,我并不是要你们为我编写程序。所以请不要生我的气:)
  • 您可以进行轮盘赌类型设置,让它们按空格键并读取计算机时钟的毫秒数。
  • 我会让你付钱给我,但你会在你的余生中这样做。太糟糕了。享受你的家庭作业。 提示阅读此docs.python.org/2/library/datetime.html
【解决方案2】:

基于random source code:

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."
    if n <= 0:
       raise ValueError
    k = n.bit_length()
    numbytes = (k + 7) // 8
    while True:
        r = int.from_bytes(random_bytes(numbytes), 'big')
        r >>= numbytes * 8 - k
        if r < n:
            return r

def random_bytes(n):
    "Return n random bytes"
    with open('/dev/urandom', 'rb') as file:
        return file.read(n)

例子:

print(randint(1, 1000))

你也可以implement random_bytes() using PRNG

【讨论】:

    【解决方案3】:

    有许多有趣的方法可以生成随机性,而无需诉诸随机(或 numpy)。例如,您可以使用内置的哈希函数:

    def rand_generator(seed, N=10**6, a=0, b=10, integer = True):
        '''For a given seed, this function returns N pseudo-random between a and b'''
        rands =[]
        if integer:
            for i in range(N):
                num = int(a+(b-a)*(abs(hash(str(hash(str(seed)+str(i+1)))))%10**13)/10**13)
                rands.append(num)
            return rands
        else:
            for i in range(N):
                num = a+(b-a)*(abs(hash(str(hash(str(seed)+str(i+1)))))%10**13)/10**13
                rands.append(num)
            return rands
    

    这将生成一个在 0 和 1 之间均匀分布的伪随机数列表。与 random 和 numpy 中的随机数生成器一样,对于给定的种子,序列是完全确定的。

    Histogram of the function's output.

    此算法在密码学上绝不是安全的,但它应该足以回答您的问题。

    如果不希望存储整个列表,那么同样的想法可以采用生成器表达式的形式。如上所述设置 a、b、N 和种子的值后:

    randnum = (int(a+(b-a)*(abs(hash(str(hash(str(seed)+str(j+1))))) % 10**13)/ 10**13) for i in range(N))
    

    是一个迭代器,它通过

    生成序列中的下一个数字
    >>> next(randnum)
        5
    

    这可以更整洁如下:

    def random(seed = None, a=0, b=10,  N=10**12, integer=True):
        '''Pass a seed to generate new sequence, otherwise next value is returned.'''
        if seed:
            print("Starting new sequence.")
            global _rand_generator 
            if integer: 
                hash_plus = lambda j: int(a + (b-a)*(abs(hash(str(hash(str(seed) + str(j+1))))) % 10**13)/ 10**13)
            else:
                hash_plus = lambda j: a + (b-a)*(abs(hash(str(hash(str(seed) + str(j+1))))) % 10**13)/ 10**13
            _rand_generator =  (hash_plus(j) for j in range(N))
        try:
            return next(_rand_generator)
        except:
            print("Random seed required.")
                
    

    要生成随机序列,请将种子传递给函数。

    >>> random(42)
    Starting new sequence.
        8 
    

    在没有种子的情况下再次调用该函数以产生序列中的下一个随机数/整数。

    >>> for i in range(10): 
    ...     print(random())
        3
        4
        6
        5
        5
        9
        2
        2
        4
        0
    

    要开始一个新序列,只需使用新种子再次调用该函数。

    >>> random(666)
    Starting new sequence.
        5
    

    【讨论】:

    • 欢迎来到 SO,并为您的第 1 次彻底回答表示敬意;但请不要在答案中包含元评论(已编辑)。
    • 请注意(隐藏在标题中)是对 int(egers) 的要求。
    • 好点,我会将转换添加到 int 作为编辑。
    猜你喜欢
    • 2012-10-04
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 2012-04-24
    • 1970-01-01
    • 2010-11-25
    • 2018-05-15
    相关资源
    最近更新 更多