How do I generate a vector of 100 64-bit integer values in the range from 1 to 20, allowing duplicates?
TL;DR:
use rand::{distributions::Uniform, Rng}; // 0.7.0
fn main() {
let range = Uniform::from(0..20);
let values: Vec<u64> = rand::thread_rng().sample_iter(&range).take(100).collect();
println!("{:?}", values);
}
It's important to use rand::distributions::uniform::Uniform instead of simply performing the modulo of a uniform random number. See Why do people say there is modulo bias when using a random number generator? for more details.
Since we are generating multiple numbers from a range, it's more performant to create the Uniform
once and reuse it. Creating the Uniform
does some computation to avoid sampling bias.
We can use Rng::sample_iter to create an iterator of random values and then take
some number of them, collecting into a Vec
. collect
will even make use of Iterator::size_hint
to allocate exactly the right number of elements.
If you only needed a single random number in the range, you could use the shortcut Rng::gen_range:
use rand::Rng; // 0.7.0
fn main() {
let mut rng = rand::thread_rng();
let value: u64 = rng.gen_range(0, 20);
}
If you needed a vector of random values without limiting to a range, you can use the Standard
distribution:
use rand::{distributions::Standard, Rng}; // 0.7.3
fn main() {
let values: Vec<u64> = rand::thread_rng().sample_iter(Standard).take(100).collect();
println!("{:?}", values);
}
There are a few main pieces that you need here. First, how to create a vector of 100 calculated items? The easiest way is to create a range of 100 and map over those items. For instance you could do:
let vals: Vec<u64> = (0..100).map(|v| v + 1000).collect();
// [1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, ...
Splitting this up:
Vec
.Expanding on this for your random values, you can adjust the .map
function to generate a random value from 0 to 20 using the rand
crate's gen_range
function to create a numeric value within a given range.
use rand::Rng; // 0.6.5
fn main() {
let mut rng = rand::thread_rng();
let vals: Vec<u64> = (0..100).map(|_| rng.gen_range(0, 20)).collect();
println!("{:?}", vals);
}
(On the Playground)
You should also consider using the rand::distributions::Uniform type to create the range up front, which is is more efficient than calling gen_range
multiple times, then pull samples from it 100 times:
use rand::{distributions::Uniform, Rng}; // 0.6.5
fn main() {
let mut rng = rand::thread_rng();
let range = Uniform::new(0, 20);
let vals: Vec<u64> = (0..100).map(|_| rng.sample(&range)).collect();
println!("{:?}", vals);
}
(On the Playground)