Closed
Description
Summary
I am trying to choose N values from vector with weights. All weights calculated as score.powf(4.)
What i expected
I expect values will be chosen so many times, in relation to their weights. Here is the weights after powf
function:
value=1 has weight=0.0000409600
value=2 has weight=0.0000000037
value=3 has weight=0.0000000207
As you can see, the lowest weight has value 2
, and i expect this value will be chosen least frequent.
What i got
got following results: {2: 100000, 3: 1, 1: 99999}
As you can see, value 2
had been choosen 100k
times, more than value 3
, that is only chosen once. Here is the score of values 2 and 3:
2: 0.0000000037
3: 0.0000000207
Note
I noticed that this happens with very small floats. Also, i guess that the initial order is matters. Both of this not mentioned in documentation, so this is either docs issue, or bug. Also i do not exclude that i may missed something, so maybe i am wrong.
Code sample
use std::collections::HashMap;
use rand::{prelude::SliceRandom, thread_rng};
fn main() {
let values: Vec<(i32, f64)> =
vec![(1, 0.080), (2, 0.0078), (3, 0.012)]
.into_iter()
.map(|v| (v.0, f64::powf(v.1, 4.0)))
.collect();
for v in &values {
println!("value={} has weight={:.10}", v.0, v.1);
}
let mut counts = HashMap::new();
for i in 0..100_000 {
let winning: Vec<i32> = values
.choose_multiple_weighted(&mut thread_rng(), 2, |a| a.1)
.unwrap()
.map(|v| v.0)
.collect();
for winner in winning {
counts.entry(winner).and_modify(|v| *v += 1).or_insert(1);
}
}
println!("got following results: {counts:?}");
assert!(counts.get(&1).unwrap() > counts.get(&2).unwrap());
assert!(counts.get(&1).unwrap() > counts.get(&3).unwrap());
assert!(counts.get(&3).unwrap() > counts.get(&2).unwrap());
}