20

I need to generate a controlled sequence of pseudo-random numbers, given an initial parameter. For that I'm using the standard python random generator, seeded by this parameter. I'd like to make sure that I will generate the same sequence across systems (Operating system, but also Python version).

In summary: Does python ensure the reproducibility / portability of it's pseudo-random number generator across implementation and versions?

Laurent Grégoire
  • 4,006
  • 29
  • 52
  • Aside (just out of interest): why do you want this? – Fred Foo Jan 09 '12 at 09:36
  • I need to generate two sequence of pseudo-random numbers on two run of a program, run that can be made by two people on two different machines. It's used for a generator of pseudo-cryptography "sheets" for a role-playing game. Don't worry, it's cryptography for a game, it *has* to be decipherable :) – Laurent Grégoire Jan 16 '12 at 10:30
  • 2
    I was hit by the change long ago (python 2.3). But it was detected, since I used a small test which checked the first numbers the random module creates. I suggest you use a test to check if the first numbers are the one you expect. – guettli May 28 '13 at 08:50

5 Answers5

13

No, it doesn't. There's no such promise in the random module's documentation.

What the docs do contain is this remark:

Changed in version 2.3: MersenneTwister replaced Wichmann-Hill as the default generator

So a different RNG was used prior to Python 2.3.

So far, I've been using numpy.random.RandomState for reproducible pseudo-randomness, though it too does not make the formal promise you're after.

If you want full reproducibility, you might want to include a copy of random's source in your program, or hack together a "P²RNG" (pseudo-pseudo-RNG) from hashlib.

cbare
  • 12,060
  • 8
  • 56
  • 63
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
3

Not necessarily.

As described in the documentation, the random module has used the Mersenne twister to generate random numbers since version 2.3, but used Wichmann-Hill before that.

(If a seed is not provided, the method of obtaining the seed also does depend on the operating system, the Python version, and factors such as the system time).

David Robinson
  • 77,383
  • 16
  • 167
  • 187
2

@reubano - 3.2 changed the integer functions in random, to produce more evenly distributed (which inevitably means different) output.

That change was discussed in Issue9025, where the team discuss whether they have an obligation to stick to the previous output, even when it was defective. They conclude that they do not. The docs for the module guarantee consistency for random.random() - one might assume that the functions which call it (like random.randrange()) are implicitly covered under that guarantee, but that doesn't seem to be the case.

Finlay McWalter
  • 1,222
  • 1
  • 10
  • 12
1

Just as a heads up: in addition to the 2.3 change, python 3 gives numbers from python 2.x from randrange and probably other functions, even if the numbers from random.random are similar.

otus
  • 5,572
  • 1
  • 34
  • 48
  • I found the opposite. `random.random` produced the same numbers across versions, while `random.randrange` gave different results. – reubano Apr 11 '17 at 12:24
1

I just found out that there is also a difference between python3.7 and python3.8.

The following code behaves the same

from random import Random
seed = 317
rand = Random(seed)
rand.getrandbits(64)

but if you use from _random import Random instead, it behaves differently.

Nic30g
  • 659
  • 6
  • 15
  • Both Python 3.6.15 and Python 3.9.16 produce `367794819093924513` on my machine for the above 4 lines. Was there a temporary issue in 3.8? – Joachim Wagner Apr 11 '23 at 18:30