0

There is Best way to generate a random float in C# for float, and Generating a Random Decimal in C# for decimal, however, there is no question for double yet which covers "the full range of double".

How to properly generate a random double with a uniform distribution over all valid (i.e., non-NaN/infinite/...) values?

D.R.
  • 20,268
  • 21
  • 102
  • 205
  • What do you mean by uniform distribution? Do you want each double to be equally likely, or do you want a mathematically uniform distribution (i.e., the chance of getting a number in the interval `[x, y]` is proportional to `(y-x)`)? – Mark Dickinson Nov 19 '17 at 18:27
  • It is not clear what you're asking. How does calling `random.NextDouble()` and then scaling that to the range `[double.MinValue, double.MaxValue]` not address your need? Why don't you just apply the answer for `float` you found, but use the `double` type instead? Have you tried _anything_? – Peter Duniho Nov 21 '17 at 05:07
  • ad float) I'm not sure how to apply the answer for double as nobody describes where the constants come from (*2.0, -1.0, -126, +128) – D.R. Nov 21 '17 at 07:45
  • ad scaling) how to do that? The old `rangeMin + (rangeMax - rangeMin) * r.nextDouble() ` does not work as it runs into overflows if r.nextDouble() is very high. – D.R. Nov 21 '17 at 07:47
  • ad distribution) I'd like it to have the same distribution as nextDouble() has. – D.R. Nov 21 '17 at 07:49

1 Answers1

1

Your scaling wouldn't work, because the scaling factor would be actually bigger than double.MaxValue which doesn't work.

var number = r.NextDouble() * 2d - 1d; // r in [-1, 1]
return number * double.MaxValue;

This code snippet first generates a uniform distributed random number in the range [-1,1]. Than it transforms it into your desired range.

This only works, when both ranges are equal, which is true for your use-case ( double.MaxValue == Math.Abs(double.MinValue))

Note: actually the upper bound of Random.NextDouble() is 0.99999999999999978 according to https://learn.microsoft.com/en-us/dotnet/api/system.random.nextdouble?view=netframework-4.7)

According to your question, how to get a range where 1 is included, you could implement the random.NextDouble() method on your own. The reference implementation (http://referencesource.microsoft.com/#mscorlib/system/random.cs,bb77e610694e64ca) uses the Random.Next() method and maps it to a double, where the Random.Next() method has a range [0, Int32.MaxValue - 1]. So just use r.Next() * (1.0 / (Int32.MaxValue - 1)) which would return double values in the range [0, 1].

By the way, I don't think, the docs are correct, since the maximum value, Random.NextDouble() can generate is 0.999999999534339, which is (Int32.MaxValue - 1) * (1.0 / Int32.MaxValue) and not 0.99999999999999978.

  • Sounds great - I'm just a little bit concerned about 1 not being in range. So the algorithm never outputs `double.MaxValue` as the result. Do you think it is possible to alter the `2d` factor to something a little bit bigger so that 1 is also included in the range? – D.R. Nov 24 '17 at 09:21