bpo-24567: Random subnormal.diff (GH-7954) (GH-7956) · python/cpython@acda5ea (original) (raw)
3 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -360,7 +360,9 @@ def choices(self, population, weights=None, *, cum_weights=None, k=1): | ||
360 | 360 | raise ValueError('The number of weights does not match the population') |
361 | 361 | bisect = _bisect.bisect |
362 | 362 | total = cum_weights[-1] |
363 | -return [population[bisect(cum_weights, random() * total)] for i in range(k)] | |
363 | +hi = len(cum_weights) - 1 | |
364 | +return [population[bisect(cum_weights, random() * total, 0, hi)] | |
365 | +for i in range(k)] | |
364 | 366 | |
365 | 367 | ## -------------------- real-valued distributions ------------------- |
366 | 368 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -220,6 +220,14 @@ def test_choices(self): | ||
220 | 220 | with self.assertRaises(IndexError): |
221 | 221 | choices([], cum_weights=[], k=5) |
222 | 222 | |
223 | +def test_choices_subnormal(self): | |
224 | +# Subnormal weights would occassionally trigger an IndexError | |
225 | +# in choices() when the value returned by random() was large | |
226 | +# enough to make `random() * total` round up to the total. | |
227 | +# See https://bugs.python.org/msg275594 for more detail. | |
228 | +choices = self.gen.choices | |
229 | +choices(population=[1, 2], weights=[1e-323, 1e-323], k=5000) | |
230 | + | |
223 | 231 | def test_gauss(self): |
224 | 232 | # Ensure that the seed() method initializes all the hidden state. In |
225 | 233 | # particular, through 2.2.1 it failed to reset a piece of state used |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
1 | +Improve random.choices() to handle subnormal input weights that could | |
2 | +occasionally trigger an IndexError. |