两个双数之间的随机数

有没有可能在两个双精度数之间生成一个随机数?

例如:

public double GetRandomeNumber(double minimum, double maximum)
{
return Random.NextDouble(minimum, maximum)
}

然后我用下面的话来称呼它:

double result = GetRandomNumber(1.23, 5.34);

有任何想法都可以。

256960 次浏览

是的。

随机。NextDouble 返回0到1之间的双精度值。然后将其乘以需要进入的范围(最大值和最小值之间的差) ,再将其加到基数(最小值)。

public double GetRandomNumber(double minimum, double maximum)
{
Random random = new Random();
return random.NextDouble() * (maximum - minimum) + minimum;
}

真正的代码应该是随机的静态成员。这将节省创建随机数生成器的成本,并使您能够非常频繁地调用 GetRRandom Number。因为我们每次调用都要初始化一个新的 RNG,所以如果你调用的足够快,以至于系统时间不会在两次调用之间发生变化,那么 RNG 就会被植入一个完全相同的时间戳,并且生成相同的随机数流。

最简单的方法就是简单地生成一个介于0和两个数字差之间的随机数。然后将两个数字中较小的一个加到结果中。

您可以使用这样的代码:

public double getRandomNumber(double minimum, double maximum) {
return minimum + randomizer.nextDouble() * (maximum - minimum);
}

你可以这样做:

public class RandomNumbers : Random
{
public RandomNumbers(int seed) : base(seed) { }


public double NextDouble(double minimum, double maximum)
{
return base.NextDouble() * (maximum - minimum) + minimum;
}
}

关于在循环中调用相同的随机数,一个漂亮的解决方案是将循环外的新 Random ()对象声明为全局变量。

注意,如果要在循环中运行此函数,则必须在 GetRRandom Int 函数之外声明 Random 类的实例。

“这是为什么?”你问。

Random 类实际上生成伪随机数,随机发生器的“种子”是系统时间。如果您的循环足够快,系统时钟时间将不会出现不同的随机发生器和随机类的每个新实例将启动相同的种子,并给你相同的伪随机数。

资料来源: http://www.whypad.com/posts/csharp-get-a-random-number-between-x-and-y/412/

Johnny5建议创建一个扩展方法:

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

现在您可以像调用 Random类的方法一样调用它:

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

请注意,您不应该在一个循环中创建大量新的 Random对象,因为这将使您很可能在一行中多次获得相同的值。如果您需要大量的随机数,那么创建一个 Random实例并重用它。

如果其中一个值是负的呢? 最好是这样:

double NextDouble(double min, double max)
{
if (min >= max)
throw new ArgumentOutOfRangeException();
return random.NextDouble() * (Math.Abs(max-min)) + min;
}
Random random = new Random();


double NextDouble(double minimum, double maximum)
{


return random.NextDouble()*random.Next(minimum,maximum);


}

注意: 如果在循环中生成 random,例如 for(int i = 0; i < 10; i++),不要将 new Random()声明放在循环中。

来自 MSDN:

随机数生成从一个种子值开始 重复使用种子,生成相同的序列号 产生不同序列的方法是使种子价值 时间依赖,从而产生一个不同的系列与每个新的 默认情况下,随机数的无参数构造函数 随机类使用系统时钟来生成它的种子值..。

因此,基于这个事实,做一些事情:

var random = new Random();


for(int d = 0; d < 7; d++)
{
// Actual BOE
boes.Add(new LogBOEViewModel()
{
LogDate = criteriaDate,
BOEActual = GetRandomDouble(random, 100, 1000),
BOEForecast = GetRandomDouble(random, 100, 1000)
});
}


double GetRandomDouble(Random random, double min, double max)
{
return min + (random.NextDouble() * (max - min));
}

通过这种方式,您可以保证得到不同的双精度值。

如果你需要一个范围内的随机数[ 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)

使用:

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;
}
}
}

我有点迟到了,但我需要实现一个通用的解决方案,结果是没有一个解决方案能满足我的需求。

公认的解决方案适用于小范围; 但是,对于大范围,maximum - minimum可以是无穷大的。所以一个更正的版本可以是这个版本:

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));
}

这样即使在 double.MinValuedouble.MaxValue之间也能很好地产生随机数。但是,这引入了另一个“问题”,这是很好地介绍了 在这个职位: 如果我们使用这么大的范围的值可能看起来太“不自然”。例如,在生成0和 double.MaxValue之间的10,000个随机双精度数之后,所有的值都在2.9579 E + 304和1.7976 E + 308之间。

因此,我还创建了另一个版本,它可以在对数尺度上生成数字:

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);
}

一些测试:

下面是使用这两种策略在0和 Double.MaxValue之间生成10,000个随机双数的排序结果。结果以对数尺度显示:

0..Double.MaxValue

虽然线性随机值乍一看似乎是错误的,但统计数据显示,它们都没有“更好”: 即使是线性策略也有一个均匀分布,两种策略的值之间的平均差异几乎是相同的。

通过处理不同的范围,我发现线性策略在0到 ushort.MaxValue之间的“合理”最小值为10.78294704时是“理智的” (对于 ulong范围,最小值为3.03518 E + 15; int:353341)。这两种战略在不同规模下的结果是相同的:

0..UInt16.MaxValue


编辑:

最近我做了我的 图书馆开放源码,随时可以看到 RandomExtensions.NextDouble方法与完整的验证。

使用一个静态随机或数字往往重复在紧/快循环,由于系统时钟播种他们。

public static class RandomNumbers
{
private static Random random = new Random();
//=-------------------------------------------------------------------
// double between min and the max number
public static double RandomDouble(int min, int max)
{
return (random.NextDouble() * (max - min)) + min;
}
//=----------------------------------
// double between 0 and the max number
public static double RandomDouble(int max)
{
return (random.NextDouble() * max);
}
//=-------------------------------------------------------------------
// int between the min and the max number
public static int RandomInt(int min, int max)
{
return random.Next(min, max + 1);
}
//=----------------------------------
// int between 0 and the max number
public static int RandomInt(int max)
{
return random.Next(max + 1);
}
//=-------------------------------------------------------------------
}

参见: https://learn.microsoft.com/en-us/dotnet/api/system.random?view=netframework-4.8

随机兰特 = 新随机() ;

下一个(1,5)/10;//表示0,1和0,5之间