Random Number Between 2 Double Numbers

后端 未结 12 2069
粉色の甜心
粉色の甜心 2020-11-27 10:25

Is it possible to generate a random number between 2 doubles?

Example:

public double GetRandomeNumber(double minimum, double maximum)
{
    return Ra         


        
相关标签:
12条回答
  • 2020-11-27 11:19
    Random random = new Random();
    
    double NextDouble(double minimum, double maximum)
    {  
    
        return random.NextDouble()*random.Next(minimum,maximum);
    
    }
    
    0 讨论(0)
  • 2020-11-27 11:20

    If you need a random number in the range [double.MinValue; double.MaxValue]

    // Because of:
    double.MaxValue - double.MinValue == double.PositiveInfinity
    
    // This will be equals to NaN or PositiveInfinity
    random.NextDouble() * (double.MaxValue - double.MinValue)
    

    Use instead:

    public static class RandomExtensions
    {
        public static double NextDoubleInMinMaxRange(this Random random)
        {
            var bytes = new byte[sizeof(double)];
            var value = default(double);
            while (true)
            {
                random.NextBytes(bytes);
                value = BitConverter.ToDouble(bytes, 0);
                if (!double.IsNaN(value) && !double.IsInfinity(value))
                    return value;
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-27 11:23

    You could use code like this:

    public double getRandomNumber(double minimum, double maximum) {
        return minimum + randomizer.nextDouble() * (maximum - minimum);
    }
    
    0 讨论(0)
  • 2020-11-27 11:25

    I'm a bit late to the party but I needed to implement a general solution and it turned out that none of the solutions can satisfy my needs.

    The accepted solution is good for small ranges; however, maximum - minimum can be infinity for big ranges. So a corrected version can be this version:

    public static double NextDoubleLinear(this Random random, double minValue, double maxValue)
    {
        // TODO: some validation here...
        double sample = random.NextDouble();
        return (maxValue * sample) + (minValue * (1d - sample));
    }
    

    This generates random numbers nicely even between double.MinValue and double.MaxValue. But this introduces another "problem", which is nicely presented in this post: if we use such big ranges the values might seem too "unnatural". For example, after generating 10,000 random doubles between 0 and double.MaxValue all of the values were between 2.9579E+304 and 1.7976E+308.

    So I created also another version, which generates numbers on a logarithmic scale:

    public static double NextDoubleLogarithmic(this Random random, double minValue, double maxValue)
    {
        // TODO: some validation here...
        bool posAndNeg = minValue < 0d && maxValue > 0d;
        double minAbs = Math.Min(Math.Abs(minValue), Math.Abs(maxValue));
        double maxAbs = Math.Max(Math.Abs(minValue), Math.Abs(maxValue));
    
        int sign;
        if (!posAndNeg)
            sign = minValue < 0d ? -1 : 1;
        else
        {
            // if both negative and positive results are expected we select the sign based on the size of the ranges
            double sample = random.NextDouble();
            var rate = minAbs / maxAbs;
            var absMinValue = Math.Abs(minValue);
            bool isNeg = absMinValue <= maxValue ? rate / 2d > sample : rate / 2d < sample;
            sign = isNeg ? -1 : 1;
    
            // now adjusting the limits for 0..[selected range]
            minAbs = 0d;
            maxAbs = isNeg ? absMinValue : Math.Abs(maxValue);
        }
    
        // Possible double exponents are -1022..1023 but we don't generate too small exponents for big ranges because
        // that would cause too many almost zero results, which are much smaller than the original NextDouble values.
        double minExponent = minAbs == 0d ? -16d : Math.Log(minAbs, 2d);
        double maxExponent = Math.Log(maxAbs, 2d);
        if (minExponent == maxExponent)
            return minValue;
    
        // We decrease exponents only if the given range is already small. Even lower than -1022 is no problem, the result may be 0
        if (maxExponent < minExponent)
            minExponent = maxExponent - 4;
    
        double result = sign * Math.Pow(2d, NextDoubleLinear(random, minExponent, maxExponent));
    
        // protecting ourselves against inaccurate calculations; however, in practice result is always in range.
        return result < minValue ? minValue : (result > maxValue ? maxValue : result);
    }
    

    Some tests:

    Here are the sorted results of generating 10,000 random double numbers between 0 and Double.MaxValue with both strategies. The results are displayed with using logarithmic scale:

    Though the linear random values seem to be wrong at first glance the statistics show that none of them are "better" than the other: even the linear strategy has an even distribution and the average difference between the values are pretty much the same with both strategies.

    Playing with different ranges showed me that the linear strategy gets to be "sane" with range between 0 and ushort.MaxValue with a "reasonable" minimum value of 10.78294704 (for ulong range the minimum value was 3.03518E+15; int: 353341). These are the same results of both strategies displayed with different scales:


    Edit:

    Recently I made my libraries open source, feel free to see the RandomExtensions.NextDouble method with the complete validation.

    0 讨论(0)
  • 2020-11-27 11:27

    About generating the same random number if you call it in a loop a nifty solution is to declare the new Random() object outside of the loop as a global variable.

    Notice that you have to declare your instance of the Random class outside of the GetRandomInt function if you are going to be running this in a loop.

    “Why is this?” you ask.

    Well, the Random class actually generates pseudo random numbers, with the “seed” for the randomizer being the system time. If your loop is sufficiently fast, the system clock time will not appear different to the randomizer and each new instance of the Random class would start off with the same seed and give you the same pseudo random number.

    Source is here : http://www.whypad.com/posts/csharp-get-a-random-number-between-x-and-y/412/

    0 讨论(0)
  • 2020-11-27 11:29

    Johnny5 suggested creating an extension method. Here's a more complete code example showing how you could do this:

    public static class RandomExtensions
    {
        public static double NextDouble(
            this Random random,
            double minValue,
            double maxValue)
        {
            return random.NextDouble() * (maxValue - minValue) + minValue;
        }
    }
    

    Now you can call it as if it were a method on the Random class:

    Random random = new Random();
    double value = random.NextDouble(1.23, 5.34);
    

    Note that you should not create lots of new Random objects in a loop because this will make it likely that you get the same value many times in a row. If you need lots of random numbers then create one instance of Random and re-use it.

    0 讨论(0)
提交回复
热议问题