C# 随机数生成-返回的数字相同

C# 随机数生成-返回的数字相同,c#,random,C#,Random,可能的重复项: 我有一个方法可以构建INT队列: public Queue<int> generateTrainingInts(int count = 60) { Queue<int> retval = new Queue<int>(); for (int i = 0; i < count; i++) { retval.Enqueue(JE_Rand.rInt(2001

可能的重复项:

我有一个方法可以构建INT队列:

public Queue<int> generateTrainingInts(int count = 60)
    {
        Queue<int> retval = new Queue<int>();

        for (int i = 0; i < count; i++)
        {
            retval.Enqueue(JE_Rand.rInt(2001, 100));
        }

        return retval;
    }
但当我调用GenerateTrainingts时,每次都会有相同的号码排队。但是,如果我将rInt更改为使用Random类的静态实例,而不是本地实例(函数范围如上所述),那么它似乎工作正常(随机整数排队)。有人知道为什么会这样吗

编辑: 亲爱的回答者,他们没有仔细阅读我的问题,
正如你们中的一些人指出的,我正在寻找一个很好的解释来解释为什么会发生这种情况。我不是在寻找一个解决同一个数字产生的问题的方法,因为我已经像上面所说的那样解决了这个问题。谢谢你的热情:)我真的只想理解这样的事情,因为我的第一个实现在概念上对我来说更有意义。

你需要保持相同的
随机对象。将其作为静态成员放在静态方法之外

private static Random rand = new Random();

public static int rInt(int exclUB, int incLB = 0)
{
    int t = rand.Next(incLB, exclUB);
    return t;
}
编辑

原因是用于初始化
随机
的时钟分辨率有限。Random的后续初始化将在随机序列中获得相同的起始位置。当重复使用同一个随机序列时,总是会生成随机序列中的下一个值。

试试下面的代码,我想你会明白其中的原因:

void PrintNowAHundredTimes()
{
    for (int i = 0; i < 100; ++i)
    {
        Console.WriteLine(DateTime.Now);
    }
}
void PrintNowAHundredTimes()
{
对于(int i=0;i<100;++i)
{
Console.WriteLine(DateTime.Now);
}
}
Random
对象一次又一次地获得相同的种子。这是因为
DateTime.Now
返回的系统时间的粒度非常简单,是有限的。例如,在我的机器上,该值仅每15毫秒更改一次。因此,在该时间段内的连续呼叫返回相同的时间

正如我猜想你们已经知道的,两个用相同种子值初始化的
Random
对象将生成相同的随机序列。(这就是为什么从技术上讲它被称为伪随机的原因。)


您还应该意识到,即使在您的方法中本地实例化一个新的
Random
对象是有意义的,但将其设置为
null
仍然没有任何意义(一旦该方法退出,将不再引用该对象,因此它将被垃圾收集)。

似乎是重复的。。。看看像这样的实际问题-之所以发生这种情况,是因为
Random
对象是从
Environment.GetTickCount
初始化的,它是一个毫秒计时器。因此,如果在同一毫秒内两次调用
Random
构造函数,将得到相同的初始值。当使用相同的种子(例如,在您的情况下为DateTime.Now.millis秒)实例化rand时,它将返回相同的值序列。您应该实例化它一次(并将其存储在静态变量中),或者每次都使用不同的种子。关于您的编辑:我认为这会让很多开发人员感到厌烦的原因是名称本身,
Random
。他们认为它是“一个随机数”。它实际上应该被称为
RandomSequence
或类似的东西。这样看来就更明显了,没有必要不断地实例化新的实例了。@Dan Tao这是一个很好的观点。虽然我一直知道“随机”意味着“伪随机”,但在实践中这些概念从未分离,即使用随机数生成器始终被视为真正的随机数,即使这不是因为实现对开发人员隐藏……OP已经尝试过了,并问为什么。为什么在生成后将rand指定为null??由于rand将在很短的时间范围内实例化,两个实例将获得相同的种子并返回相同的值,与作者的版本完全相同。您应该将其置于静态状态,并始终保持相同的实例。也可以使用具有不同种子的多个实例,例如使用“Guid.NewGuid().GetHashCode()”作为种子,但您将获得糟糕的性能。我看到您已经更正了代码示例。它是boggus,但现在应该可以工作了……我使用这个变量seed=(int)DateTime.now.Ticks;var random=新随机(种子);为什么rand=null?它将转储对象,下一个调用将抛出exception@walter:这是一个旧答案,但我只是复制和粘贴他的代码,并将新的随机(..)移动到方法调用之外。不过你是100%对的。我将编辑我的答案。
void PrintNowAHundredTimes()
{
    for (int i = 0; i < 100; ++i)
    {
        Console.WriteLine(DateTime.Now);
    }
}
public class JE_Rand
{
   private static Random rand= new Random(DateTime.Now.Millisecond);

    public static int rInt(int exclUB, int incLB = 0)
    {
        int t = rand.Next(incLB, exclUB);
        return t;
    }
}