简体   繁体   中英

Random int without importing 'random'

is there a way to let the program select a random number between say 1 and 1,000 without importing random ?

Based on 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)

Example:

print(randint(1, 1000))

You could also implement random_bytes() using PRNG .

There are many interesting ways to generate randomness without resorting to random (or numpy). For instance, you can use the built in hash function:

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

This will generate a list of uniformly distributed pseudo-random numbers between 0 and 1. Like the random number generators in random and numpy the sequence is fully deterministic for a given seed.

Histogram of the function's output.

This algorithm is in no way cryptographically safe but it should be sufficient to answer your question.

If storing the entire list undesirable then the same idea can take the form of a generator expression. After setting the values for a, b, N, and seed as above:

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

is an iterator which generates the next number in the sequence via

>>> next(randnum)
    5

This can be made even neater as follows:

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.")
            

To generate a random sequence pass a seed to the function.

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

Call the function again without a seed to yield the next random number/integer in the sequence.

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

To start a new sequence, simply call the function again with a new seed.

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

assuming you want integers.

import numpy as np
np.random.randint(1,1000)
#method one, set new seed every time random is needed


seed = "seed" #can be int or string, varies between compilings of the game
possibilities = 3 #0,1,2

hash(str(seed))%possibilities

hash(str(0))%3 #single random number between 0,1,2 (inc) seed is 0


#method two, generate a random list of numbers


size = 100 #length of list
possibilities = 2 #0,1

[hash(str(seed))%possibilities for seed in range(size)]

[hash(str(seed))%5 for seed in range(100)] #generates a list of numbers between 0,1,2,3,4 (inc) with the size of 100
hash(" ")%6


[hash(str(seed))%2 for seed in range(100)].count(1) #validity check. output is ~50

i wrote this program to help with this problem

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM