
Fixing Random - azhenley
https://ericlippert.com/2019/01/31/fixing-random-part-1/
======
azhenley
Part 2: [https://ericlippert.com/2019/02/04/fixing-random-
part-2/](https://ericlippert.com/2019/02/04/fixing-random-part-2/)

Part 3: [https://ericlippert.com/2019/02/07/fixing-random-
part-3/](https://ericlippert.com/2019/02/07/fixing-random-part-3/)

------
a1369209993
> An alternative, and possibly better solution, would be to build the double
> from bits directly, rather than doing an expensive division.

Clever trick:

    
    
      uint64 x = 0x3FF0'0000'0000'0000 |
          (rand64()&0xF'FFFF'FFFF'FFFF)
      return *(double*)&x - 1.0
    

This gives a perfect uniform distribution on [0,1), with the caveat that
everything is rounded to a multiple of 2^-52 (≈ 2.22e-16).

~~~
redcalx
See NextDoubleHighRes() here:

[https://github.com/colgreen/Redzen/blob/master/Redzen/Random...](https://github.com/colgreen/Redzen/blob/master/Redzen/Random/RandomSourceBase.cs)

There's an explanation in the comments, and a link to the original fuller
explanation and source, here:

[https://mumble.net/~campbell/tmp/random_real.c](https://mumble.net/~campbell/tmp/random_real.c)

I.e. I'm pretty sure your approach gives a non uniform distribution, but happy
to discuss in more detail if you want.

~~~
FabHK
Among the number it emits, the distribution is "uniform", but it leaves out
many possible doubles (half between 0.5 and 1, a quarter between 0.25 and 0.5,
etc.), as far as I understand.

Great sources!

(EDIT: replace "omit" by "leave out", because it's too close to "emit")

~~~
redcalx
Yeh that sounds right. Had forgotten the details as it's been a while since I
went through all the issues and wrote and tested the redzen code.

------
redcalx
There are a number of issues with System.Random, all of the known issues to
date are described in this open github issue:

[https://github.com/dotnet/corefx/issues/23298](https://github.com/dotnet/corefx/issues/23298)

The redzen library contains RNGs that address all of the known issues, e.g.
see:

[https://github.com/colgreen/Redzen/blob/master/Redzen/Random...](https://github.com/colgreen/Redzen/blob/master/Redzen/Random/RandomSourceBase.cs)

[https://github.com/colgreen/Redzen/blob/master/Redzen/Random...](https://github.com/colgreen/Redzen/blob/master/Redzen/Random/Xoshiro256StarStarRandom.cs)

That Xoshiro256StarStarRandom source has also been merged into Math.Net.

------
SOLAR_FIELDS
I personally fell victim to this very mistake he mentions when I first started
with C#. It really doesn’t follow the principle of least astonishment and it
makes me feel a bit better knowing that it’s apparently a pretty common
mistake.

------
iheartpotatoes
I'm not following his reason for writing this. In part 2 he says he doesn't
care about the performance hit from a crypto library that implements a system
TRNG, sooooo, use that?

[https://developer.mozilla.org/en-
US/docs/Web/API/Crypto/getR...](https://developer.mozilla.org/en-
US/docs/Web/API/Crypto/getRandomValues)

Or even study the thread on entropy pool paranoia from the Stanford Javascript
Crypto Library:

[https://github.com/bitwiseshiftleft/sjcl/issues/77](https://github.com/bitwiseshiftleft/sjcl/issues/77)

/scratches head at FAIC/

~~~
detaro
Why are you linking to Javascript docs under an article about why the default
C# APIs for random are bad? And even if there's already replacement libraries,
a discussion of how they can be better than the default is useful?

