This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Random.randint generates different values in Python2 and Python3
Type: behavior Stage: resolved
Components: Extension Modules, Library (Lib) Versions: Python 3.6, Python 3.5, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: SilentGhost, mark.dickinson, rhettinger, wrohdewald, ztane
Priority: normal Keywords:

Created on 2016-08-12 08:47 by wrohdewald, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
r.py wrohdewald, 2016-08-12 08:47
Messages (10)
msg272506 - (view) Author: Wolfgang Rohdewald (wrohdewald) Date: 2016-08-12 08:47
The documentation promises backwards compatible seeders. I understand this as such that they generate the same random sequences. But for Python 2.7.12 and 3.5.2 this is not so, even if I pass an integer as seed value. The attached script returns different values.

Maybe I misunderstand the documentation - I believe it means that seed(version=1) uses the backwards compatible seeder, but it does not say so explicitly. If that is not so, the documentation does not say how to invoke the backwards compatible seeder.
msg272508 - (view) Author: SilentGhost (SilentGhost) * (Python triager) Date: 2016-08-12 09:07
The rnd.random is still producing the same sequence, between versions. randint evidently doesn't, but that must be happening elsewhere.
msg272511 - (view) Author: Antti Haapala (ztane) * Date: 2016-08-12 09:46
It is this change in 3.2:

    randrange is more sophisticated about producing equally distributed
    values.  Formerly it used a style like ``int(random()*n)`` which  '
    could produce slightly uneven distributions.

-                return self._randbelow(istart)
+                if istart >= maxwidth:
+                    return self._randbelow(istart)
+                return int(self.random() * istart)

by rhettinger. Since there has not been any regression tests that the seeded numbers would stay compatible, they don't. Perhaps it would be a good idea to *add* such tests.
msg272512 - (view) Author: Antti Haapala (ztane) * Date: 2016-08-12 09:51
Sorry + and - are backwards there (I did the delta in wrong direction); + is before, and - after Raymond's commit. The `if` was retained there for backward-compatibility.
msg272513 - (view) Author: Antti Haapala (ztane) * Date: 2016-08-12 09:55
but yes, now that I read the documentation, 3.5 docs it say very explicitly that:

  Two aspects are guaranteed not to change:

    - If a new seeding method is added, then a backward compatible seeder will be offered.
    - The generator’s random() method will continue to produce the same sequence when the compatible seeder is given the same seed.

thus no guarantee is given about any other method at all, including randrange and randint.
msg272514 - (view) Author: Wolfgang Rohdewald (wrohdewald) Date: 2016-08-12 10:15
There seems to be more to it, _randbelow already returns different values. 

And _randbelow is used by other user helpers like randrange, choice, select, shuffle, sample
msg272515 - (view) Author: SilentGhost (SilentGhost) * (Python triager) Date: 2016-08-12 10:20
> There seems to be more to it

I'm not sure what "it" are you referring to. The output of randint is not guaranteed to be the same across versions, the seeded sequence is still the same between python2 and 3 - as documented.
msg272517 - (view) Author: Wolfgang Rohdewald (wrohdewald) Date: 2016-08-12 10:34
@SilentGhost: Sorry, I did not see the latest messages, I was referring to msg272511

Having to re-implement everything but rnd.random is not very user friendly. I will do that now for my project.
msg272519 - (view) Author: Antti Haapala (ztane) * Date: 2016-08-12 10:47
Anyhow, in this case it is easy to simulate the Python 2 randint behaviour (add checks for hi >= lo if needed):

    >>> random.seed(5, version=1)
    >>> randint_compat = lambda lo, hi: lo + int(random.random() * (hi + 1 - lo))
    >>> randint_compat(0, 9999999)
    6229016
msg272544 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2016-08-12 16:39
Wolfgang, sorry you bumped into this problem and glad that you have a workaround.  We only guarantee availability of backward compatible seeders and that calls to random() are reproducible.   The other methods are allowed to change so that we can make periodic improvements (i.e. using _randbelow to favor equidistribution over speed).  Marking this as not a bug and closing.
History
Date User Action Args
2022-04-11 14:58:34adminsetgithub: 71929
2016-08-12 16:46:36SilentGhostsetstage: resolved
2016-08-12 16:39:39rhettingersetstatus: open -> closed
assignee: rhettinger
resolution: not a bug
messages: + msg272544
2016-08-12 10:47:22ztanesetmessages: + msg272519
2016-08-12 10:34:18wrohdewaldsetmessages: + msg272517
2016-08-12 10:20:21SilentGhostsetmessages: + msg272515
title: Random.seed(5, version=1) generates different values in PYthon2 and Python3 -> Random.randint generates different values in Python2 and Python3
2016-08-12 10:15:22wrohdewaldsetmessages: + msg272514
2016-08-12 09:55:46ztanesetmessages: + msg272513
2016-08-12 09:51:34ztanesetmessages: + msg272512
2016-08-12 09:46:34ztanesetnosy: + ztane
messages: + msg272511
2016-08-12 09:07:13SilentGhostsetversions: + Python 3.6
nosy: + rhettinger, SilentGhost, mark.dickinson

messages: + msg272508

components: + Extension Modules
type: behavior
2016-08-12 08:47:14wrohdewaldcreate