You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If you want to be able to switch to something more efficient for large n, Knuth describes a simple O(log(n)) algorithm in TAOCP volume 4 (and attributes it to J. H. Ahrens). It's essentially a bisection search on the value, using the fact that we can use the beta distribution to generate order statistics. Here's a (too) simple Python implementation. It still needs thorough testing, and could be optimised in many ways - e.g., using sensible crossover point for n and not recursing all the way to n = 0.
@mark - Newb here and before I could see your reply, I sent a PR cos I thought simple implementation provided by Raymond Hettinger was good enough. Shall I update the PR?
@avi That's Raymond's call, but IMO there's absolutely nothing wrong with getting a reference implementation (with tests, documentation, and all the usual trimmings) in first and then making algorithmic improvements later.
[...] and then making algorithmic improvements later.
Though thinking about it, there is *one* catch: for the random module, it's nice if reproducibility isn't broken more often than necessary in released versions, so it would be best to do any algorithmic tweaking *before* 3.9.0 is released. But that still gives us some time ...
Activity
rhettinger commentedon Jun 28, 2019
This a small snippet of code I written dozens of times. It would be nice to have this in the library along with the other distributions.
mdickinson commentedon Jul 1, 2019
If you want to be able to switch to something more efficient for large
n, Knuth describes a simple O(log(n)) algorithm in TAOCP volume 4 (and attributes it to J. H. Ahrens). It's essentially a bisection search on the value, using the fact that we can use the beta distribution to generate order statistics. Here's a (too) simple Python implementation. It still needs thorough testing, and could be optimised in many ways - e.g., using sensible crossover point for n and not recursing all the way to n = 0.avinassh commentedon Jul 1, 2019
@mark - Newb here and before I could see your reply, I sent a PR cos I thought simple implementation provided by Raymond Hettinger was good enough. Shall I update the PR?
I will add the tests soon.
mdickinson commentedon Jul 1, 2019
@avi That's Raymond's call, but IMO there's absolutely nothing wrong with getting a reference implementation (with tests, documentation, and all the usual trimmings) in first and then making algorithmic improvements later.
Thanks for the PR!
mdickinson commentedon Jul 1, 2019
Though thinking about it, there is *one* catch: for the random module, it's nice if reproducibility isn't broken more often than necessary in released versions, so it would be best to do any algorithmic tweaking *before* 3.9.0 is released. But that still gives us some time ...
rhettinger commentedon Aug 23, 2019
[Avi]
Yes, please.
zkneupper commentedon May 18, 2021
Is adding random.binomialvariate() still under consideration?
I would be willing to work on this addition to Lib/random.py, as well as the accompanying tests and docs.
Should I use the type of algorithm hinted at by Mark on 2019-07-01 17:56?
gpshead commentedon May 25, 2021
A presumed optimal version of this is already available in numpy.
https://numpy.org/doc/stable/reference/random/generated/numpy.random.Generator.binomial.html
https://github.com/numpy/numpy/blob/2232a473f8713f532c8164c8cf616f7bd05f54a7/numpy/random/_generator.pyx#L2805
mdickinson commentedon May 25, 2021
I think the NumPy implementation may be from here: https://core.ac.uk/download/pdf/11007254.pdf
(though I'm struggling to find a clear citation in the NumPy source)
mdickinson commentedon May 25, 2021
Nope, that's the wrong paper. It looks as though this is the right one, but it's hidden behind a paywall: https://dl.acm.org/doi/abs/10.1145/42372.42381
GH-81620: Add random.binomialvariate() (GH-94719)