-
-
Notifications
You must be signed in to change notification settings - Fork 485
Description
The output of Rng::gen_range is different depending on whether usize is 32 bits or 64 bits on the current platform, even if the requested range is small (0..12 in my case). For example:
use rand::Rng;
use rand_core::SeedableRng;
let mut rng = rand_pcg::Pcg32::seed_from_u64(0);
for _ in 0..16 {
let x: usize = rng.gen_range(0..12);
print!("{} ", x);
}
println!();
On a 64-bits system, the output is: 4 8 6 0 5 1 5 8 9 10 11 7 6 11 1 8
On a 32-bits system, the output is: 4 1 8 0 6 1 0 8 5 11 1 9 5 5 8 6
This does not affect SliceRandom::choose, thanks to some special handling in gen_index:
Lines 699 to 710 in 7ff0fc9
| // Sample a number uniformly between 0 and `ubound`. Uses 32-bit sampling where | |
| // possible, primarily in order to produce the same output on 32-bit and 64-bit | |
| // platforms. | |
| #[inline] | |
| fn gen_index<R: Rng + ?Sized>(rng: &mut R, ubound: usize) -> usize { | |
| if ubound <= (core::u32::MAX as usize) { | |
| rng.gen_range(0..ubound as u32) as usize | |
| } else { | |
| rng.gen_range(0..ubound) | |
| } | |
| } |
This means that, contrary to my expectations, my_slice.choose(&mut rng) and my_slice[rng.gen_range(0..my_slice.len())] are not equivalent (even ignoring the case of an empty slice).
I'm not sure if this qualifies as a bug, but it definitely surprised me, and took me some time to debug. I'm also not sure if it can be fixed, and if fixing it would constitute a breaking change.
In any case it could be documented, here in the book and here on Rng::gen_range.