2个双数之间的随机数

Cod*_*ker 144 c# random

是否有可能在2个双打之间生成一个随机数?

例:

public double GetRandomeNumber(double minimum, double maximum)
{
    return Random.NextDouble(minimum, maximum) 
}
Run Code Online (Sandbox Code Playgroud)

然后我用以下内容称呼它:

double result = GetRandomNumber(1.23, 5.34);
Run Code Online (Sandbox Code Playgroud)

任何想法将不胜感激.

Mic*_*ael 309

是.

Random.NextDouble返回介于0和1之间的双精度.然后将其乘以您需要进入的范围(最大值和最小值之间的差值),然后将其添加到基数(最小值).

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

真正的代码应该是随机的静态成员.这将节省创建随机数生成器的成本,并使您能够非常频繁地调用GetRandomNumber.由于我们在每次呼叫时都在初始化一个新的RNG,如果你的呼叫足够快,系统时间不会在呼叫之间发生变化,RNG将获得完全相同的时间戳,并生成相同的随机数流.

  • 请注意,如果您在循环中调用GetRandomNumber(),它将反复生成相同的值 (33认同)
  • 可能是一个很好的扩展方法,`public double GetRandomNumber(this random random,double minimum,double maximum){...}` (13认同)
  • 我建议将种子作为种子新的Random((int)DateTime.Now.Ticks),这应该使它"更随机",即使在快速循环中. (6认同)
  • 请记住,由于Random.NextDouble永远不会返回1.0,因此该函数也永远不会等于最大数. (5认同)
  • 如果最小值为double,则不起作用.MinValue和max值为double.MaxValue.有关如何处理此用例的任何建议? (5认同)
  • @DanielSkowroński我认为你的建议是不必要的,因为[文档](http://msdn.microsoft.com/en-us/library/h343ddh9.aspx)默认隐含了类似的功能.而且你不应该在循环中创建一个新的Random实例,它应该被创建一次并重用. (3认同)
  • @DanielSkowroński那就是空构造函数的作用,所以您的建议绝对没有作用。真正的解决方案是避免一直创建新的随机实例,因为这样做成本很高。如果您担心线程化,请在拥有随机实例的字段上使用“ ThreadStaticAttribute”,并使用不完全依赖时间的种子,例如“ Guid.NewGuid()。GetHashCode()”,甚至是一个简单的计数器已添加到“ static int i;”和“ new Random(Interlocked.Decrement(ref i)* Environment.TickCount)”混合中。->每个线程一个随机数,它们都具有不同的种子。 (2认同)
  • 对于 double.MinValue、double.MaxValue 会溢出,因为 (double.MaxValue - double.MinValue) ~= 1.7e308 + 1.7e308 是 double.MaxValue 的两倍 (2认同)
  • 如果最小值和最大值是“double.MinValue”和“double.MaxValue”,这似乎不起作用。在这种情况下,它返回“Infinity”。 (2认同)

Mar*_*ers 40

Johnny5建议创建一个扩展方法.这是一个更完整的代码示例,展示了如何执行此操作:

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

现在,您可以将其称为类似于该方法的方法Random:

Random random = new Random();
double value = random.NextDouble(1.23, 5.34);
Run Code Online (Sandbox Code Playgroud)

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


Len*_*rri 9

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

来自MSDN:

随机数生成从种子值开始.如果重复使用相同的种子,则生成相同的数字序列.产生不同序列的一种方法是使种子值与时间相关,从而与每个新的Random实例产生不同的序列.默认情况下,Random类的无参数构造函数使用系统时钟生成其种子值...

所以基于这个事实,做一些事情:

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));
}
Run Code Online (Sandbox Code Playgroud)

这样做可以保证您获得不同的双倍值.


Gre*_*g D 8

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


Gyö*_*zeg 8

我参加聚会有点晚了,但我需要实施一个通用的解决方案,结果发现没有一个解决方案可以满足我的需求。

公认的解决方案适用于小范围;但是,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));
}
Run Code Online (Sandbox Code Playgroud)

这甚至在double.MinValue和之间也能很好地生成随机数double.MaxValue。但这引入了另一个“问题”,这篇文章很好地介绍了这个问题:如果我们使用如此大的范围,这些值可能看起来太“不自然”。例如,在 0 之间生成 10,000 个随机双精度后,double.MaxValue所有值都在 2.9579E+304 和 1.7976E+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);
}
Run Code Online (Sandbox Code Playgroud)

一些测试:

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

0..Double.MaxValue

尽管线性随机值乍一看似乎是错误的,但统计数据表明它们中没有一个比另一个“更好”:即使线性策略具有均匀分布,并且两种策略的值之间的平均差异几乎相同.

玩不同的范围向我展示了线性策略变得“合理”,范围介于 0 和ushort.MaxValue“合理”最小值 10.78294704(ulong范围最小值为 3.03518E+15;int:353341)。这些是用不同比例显示的两种策略的相同结果:

0..UInt16.MaxValue


编辑:

最近我将我的开源,可以随意查看RandomExtensions.NextDouble带有完整验证的方法。