Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document why we use an open interval #351

Merged
merged 1 commit into from
Apr 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions src/distributions/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,6 @@ macro_rules! float_impls {
impl Distribution<$ty> for Uniform {
/// Generate a floating point number in the open interval `(0, 1)`
/// (not including either endpoint) with a uniform distribution.
///
/// # Example
/// ```rust
/// use rand::{NewRng, SmallRng, Rng};
/// use rand::distributions::Uniform;
///
/// let val: f32 = SmallRng::new().sample(Uniform);
/// println!("f32 from (0,1): {}", val);
/// ```
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
const EPSILON: $ty = 1.0 / (1u64 << $fraction_bits) as $ty;
let float_size = mem::size_of::<$ty>() * 8;
Expand Down
24 changes: 22 additions & 2 deletions src/distributions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
/// use rand::distributions::Uniform;
///
/// let val: f32 = SmallRng::new().sample(Uniform);
/// println!("f32 from [0,1): {}", val);
/// println!("f32 from (0,1): {}", val);
/// ```
///
/// With dynamic dispatch (type erasure of `Rng`):
Expand All @@ -189,9 +189,29 @@ impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
/// let mut rng = thread_rng();
/// let mut erased_rng: &mut RngCore = &mut rng;
/// let val: f32 = erased_rng.sample(Uniform);
/// println!("f32 from [0,1): {}", val);
/// println!("f32 from (0,1): {}", val);
/// ```
///
/// # Open interval for floats
/// In theory it is possible to choose between an open interval `(0, 1)`, and
/// the half-open intervals `[0, 1)` and `(0, 1]`. All can give a distribution
/// with perfectly uniform intervals. Many libraries in other programming
/// languages default to the closed-open interval `[0, 1)`. We choose here to go
/// with *open*, with the arguments:
///
/// - The chance to generate a specific value, like exactly 0.0, is *tiny*. No
/// (or almost no) sensible code relies on an exact floating-point value to be
/// generated with a very small chance (1 in ~8 million (2^23) for `f32`, and
/// 1 in 2^52 for `f64`). What is relied on is having a uniform distribution
/// and a mean of `0.5`.
/// - Several common algorithms rely on never seeing the value `0.0` generated,
/// i.e. they rely on an open interval. For example when the logarithm of the
/// value is taken, or used as a devisor.
///
/// In other words, the guarantee some value *could* be generated is less useful
/// than the guarantee some value (`0.0`) is never generated. That makes an open
/// interval a nicer choice.
///
/// [`Exp1`]: struct.Exp1.html
/// [`StandardNormal`]: struct.StandardNormal.html
#[derive(Debug)]
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ pub trait Rng: RngCore {

/// Return a random value supporting the [`Uniform`] distribution.
///
/// [`Uniform`]: struct.Uniform.html
/// [`Uniform`]: distributions/struct.Uniform.html
///
/// # Example
///
Expand Down