我意识到这个问题已被无数次问过,但似乎每个答案都没有考虑溢出。
建议的方法如下
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
。
简单的解决方案是只使用更大的类型,但我想要一个能够在每个显式类型的两个数字之间产生随机数的解决方案,它可以处理溢出情况。
有一个很好的解决方案,因为你的问题很好,我会与你分享,因为我总是将它保存在我的积压文件中,以防万一:
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
采用它。拿它并根据您的需要进行修改。