pub trait Rng: RngCore {
fn gen<T>(&mut self) -> T
where
Standard: Distribution<T>,
{ ... }
fn gen_range<T: SampleUniform, B1, B2>(&mut self, low: B1, high: B2) -> T
where
B1: SampleBorrow<T> + Sized,
B2: SampleBorrow<T> + Sized,
{ ... }
fn sample<T, D: Distribution<T>>(&mut self, distr: D) -> T { ... }
fn sample_iter<T, D>(self, distr: D) -> DistIter<D, Self, T>ⓘNotable traits for DistIter<D, R, T>impl<D, R, T> Iterator for DistIter<D, R, T> where
D: Distribution<T>,
R: Rng, type Item = T;
where
D: Distribution<T>,
Self: Sized,
{ ... }
fn fill<T: AsByteSliceMut + ?Sized>(&mut self, dest: &mut T) { ... }
fn try_fill<T: AsByteSliceMut + ?Sized>(
&mut self,
dest: &mut T
) -> Result<(), Error> { ... }
fn gen_bool(&mut self, p: f64) -> bool { ... }
fn gen_ratio(&mut self, numerator: u32, denominator: u32) -> bool { ... }
}
Expand description
An automatically-implemented extension trait on RngCore
providing high-level
generic methods for sampling values and other convenience methods.
This is the primary trait to use when generating random values.
Generic usage
The basic pattern is fn foo<R: Rng + ?Sized>(rng: &mut R)
. Some
things are worth noting here:
- Since
Rng: RngCore
and everyRngCore
implementsRng
, it makes no difference whether we useR: Rng
orR: RngCore
. - The
+ ?Sized
un-bounding allows functions to be called directly on type-erased references; i.e.foo(r)
wherer: &mut RngCore
. Without this it would be necessary to writefoo(&mut r)
.
An alternative pattern is possible: fn foo<R: Rng>(rng: R)
. This has some
trade-offs. It allows the argument to be consumed directly without a &mut
(which is how from_rng(thread_rng())
works); also it still works directly
on references (including type-erased references). Unfortunately within the
function foo
it is not known whether rng
is a reference type or not,
hence many uses of rng
require an extra reference, either explicitly
(distr.sample(&mut rng)
) or implicitly (rng.gen()
); one may hope the
optimiser can remove redundant references later.
Example:
use rand::Rng;
fn foo<R: Rng + ?Sized>(rng: &mut R) -> f32 {
rng.gen()
}
Provided methods
fn gen<T>(&mut self) -> T where
Standard: Distribution<T>,
fn gen<T>(&mut self) -> T where
Standard: Distribution<T>,
Return a random value supporting the Standard
distribution.
Example
use rand::{thread_rng, Rng};
let mut rng = thread_rng();
let x: u32 = rng.gen();
println!("{}", x);
println!("{:?}", rng.gen::<(f64, bool)>());
Arrays and tuples
The rng.gen()
method is able to generate arrays (up to 32 elements)
and tuples (up to 12 elements), so long as all element types can be
generated.
For arrays of integers, especially for those with small element types
(< 64 bit), it will likely be faster to instead use Rng::fill
.
use rand::{thread_rng, Rng};
let mut rng = thread_rng();
let tuple: (u8, i32, char) = rng.gen(); // arbitrary tuple support
let arr1: [f32; 32] = rng.gen(); // array construction
let mut arr2 = [0u8; 128];
rng.fill(&mut arr2); // array fill
fn gen_range<T: SampleUniform, B1, B2>(&mut self, low: B1, high: B2) -> T where
B1: SampleBorrow<T> + Sized,
B2: SampleBorrow<T> + Sized,
fn gen_range<T: SampleUniform, B1, B2>(&mut self, low: B1, high: B2) -> T where
B1: SampleBorrow<T> + Sized,
B2: SampleBorrow<T> + Sized,
Generate a random value in the range [low
, high
), i.e. inclusive of
low
and exclusive of high
.
This function is optimised for the case that only a single sample is
made from the given range. See also the Uniform
distribution
type which may be faster if sampling from the same range repeatedly.
Panics
Panics if low >= high
.
Example
use rand::{thread_rng, Rng};
let mut rng = thread_rng();
let n: u32 = rng.gen_range(0, 10);
println!("{}", n);
let m: f64 = rng.gen_range(-40.0f64, 1.3e5f64);
println!("{}", m);
fn sample<T, D: Distribution<T>>(&mut self, distr: D) -> T
fn sample<T, D: Distribution<T>>(&mut self, distr: D) -> T
Sample a new value, using the given distribution.
Example
use rand::{thread_rng, Rng};
use rand::distributions::Uniform;
let mut rng = thread_rng();
let x = rng.sample(Uniform::new(10u32, 15));
// Type annotation requires two types, the type and distribution; the
// distribution can be inferred.
let y = rng.sample::<u16, _>(Uniform::new(10, 15));
fn sample_iter<T, D>(self, distr: D) -> DistIter<D, Self, T>ⓘNotable traits for DistIter<D, R, T>impl<D, R, T> Iterator for DistIter<D, R, T> where
D: Distribution<T>,
R: Rng, type Item = T;
where
D: Distribution<T>,
Self: Sized,
fn sample_iter<T, D>(self, distr: D) -> DistIter<D, Self, T>ⓘNotable traits for DistIter<D, R, T>impl<D, R, T> Iterator for DistIter<D, R, T> where
D: Distribution<T>,
R: Rng, type Item = T;
where
D: Distribution<T>,
Self: Sized,
D: Distribution<T>,
R: Rng, type Item = T;
Create an iterator that generates values using the given distribution.
Note that this function takes its arguments by value. This works since
(&mut R): Rng where R: Rng
and
(&D): Distribution where D: Distribution
,
however borrowing is not automatic hence rng.sample_iter(...)
may
need to be replaced with (&mut rng).sample_iter(...)
.
Example
use rand::{thread_rng, Rng};
use rand::distributions::{Alphanumeric, Uniform, Standard};
let rng = thread_rng();
// Vec of 16 x f32:
let v: Vec<f32> = rng.sample_iter(Standard).take(16).collect();
// String:
let s: String = rng.sample_iter(Alphanumeric).take(7).collect();
// Combined values
println!("{:?}", rng.sample_iter(Standard).take(5)
.collect::<Vec<(f64, bool)>>());
// Dice-rolling:
let die_range = Uniform::new_inclusive(1, 6);
let mut roll_die = rng.sample_iter(die_range);
while roll_die.next().unwrap() != 6 {
println!("Not a 6; rolling again!");
}
fn fill<T: AsByteSliceMut + ?Sized>(&mut self, dest: &mut T)
fn fill<T: AsByteSliceMut + ?Sized>(&mut self, dest: &mut T)
Fill dest
entirely with random bytes (uniform value distribution),
where dest
is any type supporting AsByteSliceMut
, namely slices
and arrays over primitive integer types (i8
, i16
, u32
, etc.).
On big-endian platforms this performs byte-swapping to ensure portability of results from reproducible generators.
This uses fill_bytes
internally which may handle some RNG errors
implicitly (e.g. waiting if the OS generator is not ready), but panics
on other errors. See also try_fill
which returns errors.
Example
use rand::{thread_rng, Rng};
let mut arr = [0i8; 20];
thread_rng().fill(&mut arr[..]);
Fill dest
entirely with random bytes (uniform value distribution),
where dest
is any type supporting AsByteSliceMut
, namely slices
and arrays over primitive integer types (i8
, i16
, u32
, etc.).
On big-endian platforms this performs byte-swapping to ensure portability of results from reproducible generators.
This is identical to fill
except that it uses try_fill_bytes
internally and forwards RNG errors.
Example
use rand::{thread_rng, Rng};
let mut arr = [0u64; 4];
thread_rng().try_fill(&mut arr[..])?;
Return a bool with a probability of numerator/denominator
of being
true. I.e. gen_ratio(2, 3)
has chance of 2 in 3, or about 67%, of
returning true. If numerator == denominator
, then the returned value
is guaranteed to be true
. If numerator == 0
, then the returned
value is guaranteed to be false
.
See also the Bernoulli
distribution, which may be faster if
sampling from the same numerator
and denominator
repeatedly.
Panics
If denominator == 0
or numerator > denominator
.
Example
use rand::{thread_rng, Rng};
let mut rng = thread_rng();
println!("{}", rng.gen_ratio(2, 3));