Skip to content

Commit

Permalink
accurate IteratorRandom::choose()
Browse files Browse the repository at this point in the history
f64 reciprocal is inexact, with residuals on the order of 1 / 2^54.

For example: the probability gen_bool(1.0 / 3) == true is:
6004799503160661/18014398509481984
Using gen_range is exact for all values of `consumed`.

NOTE: this is a value stability-breaking change

fixes #1058
  • Loading branch information
kazcw committed Oct 16, 2020
1 parent dab98b3 commit a37a599
Showing 1 changed file with 2 additions and 3 deletions.
5 changes: 2 additions & 3 deletions src/seq/mod.rs
Expand Up @@ -336,8 +336,7 @@ pub trait IteratorRandom: Iterator + Sized {
return result;
}
consumed += 1;
let denom = consumed as f64; // accurate to 2^53 elements
if rng.gen_bool(1.0 / denom) {
if gen_index(rng, consumed) == 0 {
result = elem;
}
}
Expand Down Expand Up @@ -963,7 +962,7 @@ mod test {

assert_eq!(choose([].iter().cloned()), None);
assert_eq!(choose(0..100), Some(33));
assert_eq!(choose(UnhintedIterator { iter: 0..100 }), Some(76));
assert_eq!(choose(UnhintedIterator { iter: 0..100 }), Some(40));
assert_eq!(
choose(ChunkHintedIterator {
iter: 0..100,
Expand Down

0 comments on commit a37a599

Please sign in to comment.