Struct urandom::distributions::Uniform
source · pub struct Uniform<T: SampleUniform>(_);
Expand description
Sample values uniformly between two bounds.
Uniform
values can be constructed from a Range
or RangeInclusive
.
See below for a demonstration.
Steps are taken to avoid bias which might be present in naive implementations;
for example rng.next::<u8>() % 170
samples from the interval [0, 170)
but is twice as likely to select numbers less than 85 than other values.
Further, the implementations here give more weight to the high bits generated by the Rng than the low bits,
since with some Rngs the low bits are of lower quality than the high bits.
Implementations must sample within the given interval. It is a bug if an implementation returns a result outside the requested interval.
For one-off samples see also: Random::range
for convenient samples directly from the Rng
.
For more than one sample it is recommended to reuse the Uniform
instance.
Examples
use urandom::distributions::{Distribution, Uniform};
let between = Uniform::from(10..10000);
let mut rng = urandom::new();
let mut sum = 0;
for _ in 0..1000 {
sum += between.sample(&mut rng);
}
println!("{}", sum);
Custom implementations
Different types may have completely different uniform sampling implementations (such as the integers vs floating point types).
Start by creating a custom sampler struct which will later be linked to the Uniform
type.
For your custom sampler implement Distribution
for your custom type and UniformSampler
to add constructors to it.
Once that’s done you can specify that your custom type uses your custom sampler by implementing SampleUniform
and pointing its associated Sampler
type to your custom sampler.
use urandom::{Distribution, Random, Rng};
use urandom::distributions::{SampleUniform, UniformFloat, UniformSampler};
// The custom type for which to implement uniform sampling.
struct MyF32(f32);
// The custom sampler for the type.
struct UniformMyF32(UniformFloat<f32>);
// Add constructors for your sampler.
impl UniformSampler<MyF32> for UniformMyF32 {
fn new(low: MyF32, high: MyF32) -> Self {
UniformMyF32(UniformFloat::new(low.0, high.0))
}
fn new_inclusive(low: MyF32, high: MyF32) -> Self {
UniformMyF32(UniformFloat::new_inclusive(low.0, high.0))
}
}
// Make it a Distribution.
impl Distribution<MyF32> for UniformMyF32 {
fn sample<R: Rng + ?Sized>(&self, rng: &mut Random<R>) -> MyF32 {
MyF32(self.0.sample(rng))
}
}
// Tell everyone where to find the uniform sampler for your type.
impl SampleUniform for MyF32 {
type Sampler = UniformMyF32;
}
// Now it can be used to generate random samples.
let mut rng = urandom::new();
let value = rng.range(MyF32(13.0)..MyF32(42.0));
assert!(value.0 >= 13.0 && value.0 < 42.0);
Trait Implementations
sourceimpl<T: SampleUniform> Distribution<T> for Uniform<T>
impl<T: SampleUniform> Distribution<T> for Uniform<T>
sourceimpl<T: SampleUniform> From<Range<T>> for Uniform<T>
impl<T: SampleUniform> From<Range<T>> for Uniform<T>
sourceimpl<T: SampleUniform> From<RangeInclusive<T>> for Uniform<T>
impl<T: SampleUniform> From<RangeInclusive<T>> for Uniform<T>
sourcefn from(range: RangeInclusive<T>) -> Uniform<T>
fn from(range: RangeInclusive<T>) -> Uniform<T>
sourceimpl<T: SampleUniform> UniformSampler<T> for Uniform<T>
impl<T: SampleUniform> UniformSampler<T> for Uniform<T>
sourcefn new(low: T, high: T) -> Self
fn new(low: T, high: T) -> Self
[low, high)
(excluding high).
May panic if low >= high
. Read moresourcefn new_inclusive(low: T, high: T) -> Self
fn new_inclusive(low: T, high: T) -> Self
[low, high]
(inclusive).
May panic if low > high
. Read more