Skip to content

gh-149221:Fix binomialvariate Function for random module#149222

Open
lighting9999 wants to merge 20 commits intopython:mainfrom
lighting9999:patch-1
Open

gh-149221:Fix binomialvariate Function for random module#149222
lighting9999 wants to merge 20 commits intopython:mainfrom
lighting9999:patch-1

Conversation

@lighting9999
Copy link
Copy Markdown

@lighting9999 lighting9999 commented May 1, 2026

Fix:
Replace _log2(random()) with _log2(1.0 - random()). This matches the standard algorithm (1.0 - random() is never zero), produces the correct distribution, and eliminates the crash.

@lighting9999 lighting9999 requested a review from rhettinger as a code owner May 1, 2026 11:27
@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented May 1, 2026

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@python-cla-bot
Copy link
Copy Markdown

python-cla-bot Bot commented May 1, 2026

All commit authors signed the Contributor License Agreement.

CLA signed

@lighting9999 lighting9999 changed the title gh-149221:Fix binomialvariate Function for random gh-149221:Fix binomialvariate Function for random module May 1, 2026
Comment thread Misc/NEWS.d/next/图书馆/2026-05-01-11-31-03.gh-issue-149221.lOw7Dy.rst Outdated
…y.rst

Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
skirpichev
skirpichev previously approved these changes May 1, 2026
Comment thread Lib/random.py Outdated
@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented May 1, 2026

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@lighting9999
Copy link
Copy Markdown
Author

一位Python核心开发人员要求在考虑合并之前对你的拉取请求做一些修改。如果你能回应他们的请求,以及核心开发者在其他评测中提出的任何请求,我将非常感激。

完成请求修改后,请在本拉取请求中留言,包含短语。然后我会通知所有留下评价的核心开发者,你准备好让他们重新审视这个拉取请求。I have made the requested changes; please review again

I have made the requested changes; please review again.

@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented May 1, 2026

Thanks for making the requested changes!

@rhettinger: please review the changes made to this pull request.

@bedevere-app bedevere-app Bot requested a review from rhettinger May 1, 2026 15:00
Comment thread Misc/NEWS.d/next/图书馆/2026-05-01-11-31-03.gh-issue-149221.lOw7Dy.rst Outdated
Copy link
Copy Markdown
Member

@skirpichev skirpichev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's not too hard to find a seed, that trigger an exception. Maybe issue worth a test?

Comment thread Lib/random.py Outdated
Comment thread Misc/NEWS.d/next/图书馆/2026-05-01-11-31-03.gh-issue-149221.lOw7Dy.rst Outdated
@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented May 2, 2026

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@read-the-docs-community
Copy link
Copy Markdown

read-the-docs-community Bot commented May 2, 2026

Documentation build overview

📚 cpython-previews | 🛠️ Build #32506794 | 📁 Comparing e315b38 against main (be9c7cb)

  🔍 Preview build  

30 files changed · ± 30 modified

± Modified

@lighting9999 lighting9999 requested a review from skirpichev May 2, 2026 01:10
    # Test for pythongh-149222: binomialvariate should not crash when random()
@lighting9999 lighting9999 reopened this May 2, 2026
@lighting9999
Copy link
Copy Markdown
Author

ok @skirpichev ,Please review.

Comment thread Lib/random.py Outdated
Comment on lines +843 to +845
if c < 0:
# When c < 0, log(0) mathematically gives +infinity, so y > n.
y = n + 1
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can do a quick exit:

Suggested change
if c < 0:
# When c < 0, log(0) mathematically gives +infinity, so y > n.
y = n + 1
return x

Remember, c < 0 at this point.

Comment thread Lib/random.py Outdated
Comment thread Lib/test/test_random.py Outdated
Comment thread Lib/test/test_random.py Outdated
@skirpichev skirpichev dismissed their stale review May 2, 2026 01:51

stale

@rhettinger
Copy link
Copy Markdown
Contributor

@skirpichev Can you let me focus on this one? We're pushing the OP in two different directions.

Comment thread Lib/random.py
@@ -0,0 +1,2 @@
Fix rare math domain error for :func:`random.binomialvariate`, using
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is out of date.

Comment thread Lib/random.py Outdated
Comment thread Lib/random.py Outdated
Comment thread Lib/random.py Outdated
y += _floor(_log2(random()) / c) + 1
except ValueError:
# Handle rare case of log(0.0)
if c < 0:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please just turn the handler into a continue for a reselection. Jumping to infinity isn't desirable. I don't want to distort the distribution.

@bedevere-app
Copy link
Copy Markdown

bedevere-app Bot commented May 2, 2026

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@skirpichev
Copy link
Copy Markdown
Member

Can you let me focus on this one? We're pushing the OP in two different directions.

Sure, @rhettinger, sorry for the noise. Though, I think the only difference is that you suggest to use "continue" statement instead of "return x".

lighting9999 and others added 3 commits May 2, 2026 11:13
Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
Co-authored-by: Sergey B Kirpichev <skirpichev@gmail.com>
Comment thread Lib/random.py Outdated
@rhettinger
Copy link
Copy Markdown
Contributor

This is all that is needed:

diff --git a/Lib/random.py b/Lib/random.py
index c89cbb755ab..2460ac3d986 100644
--- a/Lib/random.py
+++ b/Lib/random.py
@@ -836,7 +836,11 @@ def binomialvariate(self, n=1, p=0.5):
             if not c:
                 return x
             while True:
-                y += _floor(_log2(random()) / c) + 1
+                try:
+                    y += _floor(_log2(random()) / c) + 1
+                except ValueError:
+                    # Handle rare case of where random() gives 0.0
+                    continue
                 if y > n:
                     return x
                 x += 1

@lighting9999
Copy link
Copy Markdown
Author

lighting9999 commented May 2, 2026

This is all that is needed:

diff --git a/Lib/random.py b/Lib/random.py
index c89cbb755ab..2460ac3d986 100644
--- a/Lib/random.py
+++ b/Lib/random.py
@@ -836,7 +836,11 @@ def binomialvariate(self, n=1, p=0.5):
             if not c:
                 return x
             while True:
-                y += _floor(_log2(random()) / c) + 1
+                try:
+                    y += _floor(_log2(random()) / c) + 1
+                except ValueError:
+                    # Handle rare case of where random() gives 0.0
+                    continue
                 if y > n:
                     return x
                 x += 1

What I originally had in mind was this:

u = random()
if u == 0.0:
    continue
y += _floor(_log2(u) / c) + 1

No try-except, just a simple check and skip. @rhettinger

@rhettinger
Copy link
Copy Markdown
Contributor

I prefer the zero-cost try/except to not slow down the loop.

@lighting9999
Copy link
Copy Markdown
Author

I prefer the zero-cost try/except to not slow down the loop.

Ok wait to change

Handle ValueError in random number generation loop.
@lighting9999
Copy link
Copy Markdown
Author

I prefer the zero-cost try/except to not slow down the loop.

please review this @rhettinger.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants