Skip to content

Commit f6d1259

Browse files
authored
Merge pull request #351 from pitdicker/float_doc
Document why we use an open interval
2 parents dba18b8 + 040895d commit f6d1259

File tree

3 files changed

+23
-12
lines changed

3 files changed

+23
-12
lines changed

src/distributions/float.rs

-9
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,6 @@ macro_rules! float_impls {
4545
impl Distribution<$ty> for Uniform {
4646
/// Generate a floating point number in the open interval `(0, 1)`
4747
/// (not including either endpoint) with a uniform distribution.
48-
///
49-
/// # Example
50-
/// ```rust
51-
/// use rand::{NewRng, SmallRng, Rng};
52-
/// use rand::distributions::Uniform;
53-
///
54-
/// let val: f32 = SmallRng::new().sample(Uniform);
55-
/// println!("f32 from (0,1): {}", val);
56-
/// ```
5748
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> $ty {
5849
const EPSILON: $ty = 1.0 / (1u64 << $fraction_bits) as $ty;
5950
let float_size = mem::size_of::<$ty>() * 8;

src/distributions/mod.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
236236
/// use rand::distributions::Uniform;
237237
///
238238
/// let val: f32 = SmallRng::new().sample(Uniform);
239-
/// println!("f32 from [0,1): {}", val);
239+
/// println!("f32 from (0,1): {}", val);
240240
/// ```
241241
///
242242
/// With dynamic dispatch (type erasure of `Rng`):
@@ -248,9 +248,29 @@ impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
248248
/// let mut rng = thread_rng();
249249
/// let mut erased_rng: &mut RngCore = &mut rng;
250250
/// let val: f32 = erased_rng.sample(Uniform);
251-
/// println!("f32 from [0,1): {}", val);
251+
/// println!("f32 from (0,1): {}", val);
252252
/// ```
253253
///
254+
/// # Open interval for floats
255+
/// In theory it is possible to choose between an open interval `(0, 1)`, and
256+
/// the half-open intervals `[0, 1)` and `(0, 1]`. All can give a distribution
257+
/// with perfectly uniform intervals. Many libraries in other programming
258+
/// languages default to the closed-open interval `[0, 1)`. We choose here to go
259+
/// with *open*, with the arguments:
260+
///
261+
/// - The chance to generate a specific value, like exactly 0.0, is *tiny*. No
262+
/// (or almost no) sensible code relies on an exact floating-point value to be
263+
/// generated with a very small chance (1 in ~8 million (2^23) for `f32`, and
264+
/// 1 in 2^52 for `f64`). What is relied on is having a uniform distribution
265+
/// and a mean of `0.5`.
266+
/// - Several common algorithms rely on never seeing the value `0.0` generated,
267+
/// i.e. they rely on an open interval. For example when the logarithm of the
268+
/// value is taken, or used as a devisor.
269+
///
270+
/// In other words, the guarantee some value *could* be generated is less useful
271+
/// than the guarantee some value (`0.0`) is never generated. That makes an open
272+
/// interval a nicer choice.
273+
///
254274
/// [`Exp1`]: struct.Exp1.html
255275
/// [`StandardNormal`]: struct.StandardNormal.html
256276
#[derive(Debug)]

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ pub trait Rng: RngCore {
417417

418418
/// Return a random value supporting the [`Uniform`] distribution.
419419
///
420-
/// [`Uniform`]: struct.Uniform.html
420+
/// [`Uniform`]: distributions/struct.Uniform.html
421421
///
422422
/// # Example
423423
///

0 commit comments

Comments
 (0)