5

I want to generate a random seed in a predictable way.

I was hoping to do this

seed = 12345
prng_0 = random.Random(seed)
prng_1 = random.Random(prng_0.rand_int(0))

There, 0 is the lower bound, but it turns out I need to give it an upper bound as well. I don't want to set a fixed upper bound.

If you are curious about my reason, I'm doing this because I need reproducibility when testing. Namely, this is a function receiving a seed and building its prng, prng_0, then calling multiple times another function that needs to receive a different seed every time.

def funct_a(seed=None):
    prng_1 = random.Random(seed)
    prng_2 = numpy.random.RandomState(prng_1.randint(0, 4294967296))
    print(prng_1.random())
    print(prng_2.random())

def funct_b(seed=None):
    prng_0 = random.Random(seed)
    for i in range(0, 5):
        seed = prng_0.randint(0)  # not working, needs upper bound
        funct_a(seed)

funct_b(12345)  # test call

EDIT: interestingly enough, numpy (which I'm also using) has a definite upper seed value, as testified by the doc and by this error

ValueError: Seed must be between 0 and 4294967295

Agostino
  • 2,723
  • 9
  • 48
  • 65
  • 5
    If you don't want an upper bound, what sort of distribution would you like? It certainly can't be uniform. – Greg Hewgill Jun 09 '15 at 01:44
  • @GregHewgill I don't get it why it can't be uniform. I know the seed is initualized using the system time, so it's probably not longer than 64 bits. What would you suggest to avoid putting an artificially low upper bound? – Agostino Jun 09 '15 at 01:55
  • 2
    @Agostino If it is a uniform distribution over an infinite range the probability of picking any value is 0. Reminds me of this question: http://stackoverflow.com/q/30118305/1726343 – Asad Saeeduddin Jun 09 '15 at 01:56
  • You can set an upper bound of 0xffffffffffffffff if you want a 64-bit unsigned integer result. However, that is very different from having *no* upper bound at all. – Greg Hewgill Jun 09 '15 at 01:57
  • OK, and what about the "can't be uniform" bit? I didn't understand that. – Agostino Jun 09 '15 at 01:58
  • 1
    @Agostino: When you start dealing with infinities, things can get weird. Consider this: Suppose you could define a uniform distribution with a lower bound 0. Then, what would the *median* value of the distribution be? (The median is the value where half the distribution is below and half is above.) Any finite value you choose would be wrong, because there would still be an infinite amount of distribution greater than your chosen value. You end up with the paradoxical idea of the median being "infinity", which doesn't make sense. – Greg Hewgill Jun 09 '15 at 02:06
  • @Agostino: In a bounded uniform distribution [a, b], the median would be (a + b) / 2. – Greg Hewgill Jun 09 '15 at 02:14
  • there can't be an unbounded generator, you could have very very large bound, but unbounded can never be possible if you want true randomness. – Abhishek Choudhary Apr 20 '22 at 19:25

3 Answers3

9

When I don't want an upper bound I'll often use sys.maxint for the upper bound as an approximation

Eric Renouf
  • 13,950
  • 3
  • 45
  • 67
3

You can't avoid an upper bound. How would the code work without one? This is how the code generates a random number between x and y:

0______________________________________________r__________________________________________1

r is a random decimal between 0 and 1. This is generated with a fixed algorithm.

Then, it takes r and multiplies it by the upper bound minus the lower bound. This pretty much means that 0 becomes x, and 1 becomes y. If rand is the random number, r : (1 - 0) :: rand : (y - x)

EDIT: There actually is a way to generate a random number without an upper bound, but it is not logarithmically and not uniformly distributed. Take a look at this python algorithm:

import random
def randint():
    i = 0
    while True:
        if random.random() < 0.5: # Or whatever other probability you want
            return i
        else:
            i += 1

Pretty much, what this is doing is starting from zero, and then every time it has a 0.5 probability of returning that number; otherwise it continues.

This means that there is a 0.5 probability of it being 0, 25% for 1, 12.5% for 2, 5.25% for 3, etc. This is logarithmic distribution "without an upper bound".

hyper-neutrino
  • 5,272
  • 2
  • 29
  • 50
  • I just need to avoid putting artificial restrictions to the seed. To make myself clear, in Java I would simply call [nextInt](http://docs.oracle.com/javase/7/docs/api/java/util/Random.html#nextInt%28%29) and take the absolute value. What would you suggest for my needs? – Agostino Jun 09 '15 at 01:50
  • 2
    There is no such thing as "no artificial restrictions" to the seed. Plus, rand is not truly random, so if you're looking for cryptographic random numbers, you should use a different protocol. What you want is a semi-random number within the full scale of possible postive integers, or long integers (which in Python have unlimited precision, so that designation is meaningless). @Eric Renouf's answer seems to satisfy that request. – Alex Huszagh Jun 09 '15 at 01:59
0

Mathematically there does not exist a uniform distribution on an unbounded set of integers (this was correctly pointed out in the commends). +1 to that comment to Eric Renouf's answer.

For posterity, the issue is that the probabilities of every possible outcome must collectively sum to a total value of 1 (that's part of the definition of a probability distribution). If the chance of choosing any one integer is a positive value p>0, then when you sum up infinitely many of those (\sum_np), you get a total of infinity, not 1. This is the outcome for any positive p>0. But if p=0, then you instead get a total of 0, not 1. You could say that "in theory" there is no such thing as random integer without an upper bound.