-
-
Notifications
You must be signed in to change notification settings - Fork 473
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
.