top | item 44160211

(no title)

j_not_j | 9 months ago

[flagged]

discuss

order

cornstalks|9 months ago

> If it is not [0,1) then it's not useful.

I can understand [0, 1) being useful in some use cases but saying it's entirely useless is a bit dramatic, don't you think? I've certainly had uses for [0, 1].

listeria|9 months ago

weirdly enough, the provided implementation of rand_float() actually generates numbers in the interval [0, 1).

I haven't read the implementation of _generate_canonical_generic(), but the following special case in generate_canonical() applies here:

  if constexpr (prng_is_bit_uniform && sizeof(T) == 4 && sizeof(generated_type) == 8) {
    return (static_cast<std::uint32_t>(gen()) >> exponent_bits_32) * mantissa_hex_32;
  }
which boils down to:

  return (static_cast<std::uint32_t>(gen()) >> 8) * 0x1.p-24;
that is, a number in the interval [0, 2^24) divided by 2^24.

GeorgeHaldane|9 months ago

Thank you for noticing! Turns out [0, 1] is an artifact of the old documentation carried back from the time where generic GCC / clang approach used to produce occasional 1's due to some issues in N4958 specification. This is fixed in a new commit.

For floats there are essentially 3 approaches that are selected based on the provided range & PRNG:

  1) Shift + multiply (like `(rng >> 11) * 0x1.0p-53`)
  2) "Low-high" from the paper by J. Doornik
  https://www.doornik.com/research/randomdouble.pdf
  3) Canonical GCC implementation
All of these generate values in [0, 1) range which is now reflected in the docs properly. For most actual cases 1st method is the one selected.

HeliumHydride|9 months ago

This article shows how to generate perfectly-distributed random floats: https://specbranch.com/posts/fp-rand/

glkindlmann|9 months ago

That page ends with "This is the first efficient algorithm for generating random uniform floating-point numbers that can access the entire range of floating point outputs with correct probabilities". I am very skeptical.

The same basic idea is described here [1] (though without any pretty pictures, but with a link to working code), and I know others have implemented the same insight [2].

This seems like the kind of thing that is reinvented every time some who cares about random numbers learns how IEEE 754 works.

[1] http://mumble.net/~campbell/2014/04/28/uniform-random-float

[2] https://github.com/camel-cdr/cauldron/blob/a673553dd7925b0f1...