两个数字之间的随机数而不会溢出

时间:2018-09-16 04:42:07

标签: c# random

我知道这个问题已经问过无数次了,但是似乎每个答案都没有考虑到溢出问题。

建议的方法如下

public static double BoundedNext( double min, double max )
{
  var random = new Random( Guid.NewGuid().GetHashCode() );
  return ( random.NextDouble() * ( max - min ) ) + min;
}

在几乎每种情况下,这种方法都可以正常工作。但是,它不能正确处理发生溢出的情况,例如BoundedNext(Double.MinValue, Double.MaxValue)。在像C#这样的语言中,问题变得更加棘手,其中double等于-/+ infinity

简单的解决方案是只使用较大的类型,但是我希望能够为两个显式类型生成两个数字之间的随机数的解决方案,以解决溢出情况。 >

1 个答案:

答案 0 :(得分:0)

有一个很好的解决方案,因为您的问题很到位,我将与您分享它,因为我总是将其保存在积压文件中,以防万一:

  static Random random = new Random();

    // Note, max is exclusive here!
    public static List<int> GenerateRandom(int count, double min, double max)
    {

        if (max <= min || count < 0 || 
                // max - min > 0 required to avoid overflow
                (count > max - min && max - min > 0))
        {
            // need to use 64-bit to support big ranges (negative min, positive max)
            throw new ArgumentOutOfRangeException("Range " + min + " to " + max + 
                    " (" + ((Double)max - (Double)min) + " values), or count " + count + " is illegal");
        }

        // generate count random values.
        HashSet<int> candidates = new HashSet<int>();

        // start count values before max, and end at max
        for (double top = max - count; top < max; top++)
        {
            // May strike a duplicate.
            // Need to add +1 to make inclusive generator
            // +1 is safe even for MaxVal max value because top < max
            if (!candidates.Add(random.Next(min, top + 1))) {
                // collision, add inclusive max.
                // which could not possibly have been added before.
                candidates.Add(top);
            }
        }

        // load them in to a list, to sort
        List<int> result = candidates.ToList();

        // shuffle the results because HashSet has messed
        // with the order, and the algorithm does not produce
        // random-ordered results (e.g. max-1 will never be the first value)
        for (int i = result.Count - 1; i > 0; i--)
        {  
            int k = random.Next(i + 1);  
            int tmp = result[k];  
            result[k] = result[i];  
            result[i] = tmp;  
        }  
        return result;
    }

    public static List<int> GenerateRandom(int count)
    {
        return GenerateRandom(count, 0, Double.MaxValue);
    }

此解决方案是用Int64编写的,因此我尽力为double采纳。 接受并根据您的需要进行修改。

  • 请注意注释,其中提出了避免溢出所需的条件