关于c#:Random.Next始终返回相同的值

Random.Next returns always the same values

本问题已经有最佳答案,请猛点这里访问。

我使用这个方法生成唯一的数字,但我总是得到相同的数字-2147483648。即使我停止程序,重新编译并再次运行,我仍然看到相同的数字。

1
2
3
4
5
6
7
  public static int GetRandomInt(int length)
    {          
        var min = Math.Pow(10, length - 1);
        var max = Math.Pow(10, length) - 1;
        var random = new Random();
        return random.Next((int)min, (int)max);
    }


尝试外部化随机实例:

1
2
3
4
5
6
7
8
private readonly Random _random = new Random();

public static int GetRandomInt(int length)
{          
    var min = Math.Pow(10, length - 1);
    var max = Math.Pow(10, length) - 1;
    return _random.Next((int)min, (int)max);
}


这不是不重用随机实例的问题,他得到的结果应该是多个启动时的随机结果,而不是总是-(2^32)

这是长度太大的问题,将长度的幂赋给int。如果将代码分成以下几行:

1
2
3
4
5
6
        var min = Math.Pow(10, length - 1);
        var max = Math.Pow(10, length) - 1;
        var random = new Random();
        var a = (int)min;
        var b = (int)max;
        return random.Next(a, b);

您将看到a和b是-2147483648,这使得Next(min, max)的唯一可能结果(文档指定了min==max,返回min)。

使用此方法可以安全使用的最大长度是9。如果长度为10,则得到System.ArgumentOutOfRangeException,如果长度大于10,则得到-2147483648结果。


您的代码有三个问题。

  • 您应该将随机变量外部化。
  • 截断错误有问题。
  • 最小值和最大值之间的范围很大。
  • 第一个问题是,在重新初始化随机变量时,您可能没有足够的时间提前种子。第二个错误是将(非常大的)数字截断为整数。最后,您最大的问题是您的最小值和最大值之间的范围。考虑使用输入1->20查找最小值和最大值之间的范围(如代码中定义的那样):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    length  max-min        
    1       8
    2       89
    3       899
    4       8999
    5       89999
    6       899999
    7       8999999
    8       89999999
    9       899999999
    10      8,999,999,999
    11      89999999999
    12      899999999999
    13      8999999999999
    14      89999999999999
    15      899999999999999
    16      9E+15
    17      9E+16
    18      9E+17
    19      9E+18

    请记住,最大整数是2147483647,它传递给任何大于9的数字。


    您应该一直保持一个随机的实例而不是新的(),这样可以得到更好的结果。

    还要检查实际长度。它可能会给你带来一些有趣的结果。


    我认为问题在于计算minmax。他们会比Int32.MaxValue更快…


    这篇文章已经讨论了数百次。StackOverflow的常见问题解答


    Random实例应该只创建一次,然后重用。原因是,RNG默认为当前系统时间的种子。如果您快速地创建新的随机实例(并从中提取一个值),那么它们中的许多都将以相同的时间戳作为种子,因为循环的执行速度可能比系统时钟的前进速度快。

    记住,由种子A初始化的RNG总是返回序列B。因此,如果您创建三个Random实例,所有这些实例都是以123为种子的,那么这三个实例在相同的迭代中总是返回相同的数字。


    随机类通常使用一个种子来初始化自己,并且通常返回相同的序列,前提是种子是相同的:

    • 总是重复使用同一个random()实例,而不是一次又一次地重新创建一个。
    • 如果您想要不可预知的结果,请使用时间依赖的种子而不是硬编码的种子。

    真正的随机数生成器很难编码。大多数方法使用外部熵发生器(如鼠标移动、CPU温度,甚至复杂的物理机制,如氦气球相互碰撞…)。


    在你的课堂上,有一个随机的例子,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class MyClass
    {
    private readonly Random random = new Random();

    public static int GetRandomInt(int length)
    {
      var min = Math.Pow(10, length - 1);
      var max = Math.Pow(10, length) - 1;
      return random.Next((int)min, (int)max);
    }

    }

    Random总是返回相同的值,这一事实只存在于测试目的中。