为什么Random.Next()总是返回相同的数字

时间:2011-03-10 18:58:33

标签: c# random clr

考虑这种方法:

private static int GenerateRandomNumber(int seed, int max)
{
   return new Random(seed).Next(max);
}

在我的机器上,执行此循环会产生相同数量的1500次迭代:

  for (int i = 0; i < 1501; i++)
            {
                int random = GenerateRandomNumber(100000000, 999999999);
                Console.WriteLine(random.ToString());
                Console.ReadKey();
            }

每次迭代我得到145156561。

我没有一个紧迫的问题,我只是对这种行为感到好奇,因为.Next(max)说“返回非负的随机数字小于指定的最大值。也许我不是理解一些基本的东西。

7 个答案:

答案 0 :(得分:39)

你总是使用相同的种子播种一个新实例,然后抓住第一个最大值。通过使用种子,您可以保证相同的结果。

如果你想拥有一个产生不同结果的静态随机数生成,你应该重做一下。但是,由于Random不是线程安全的,因此静态使用时需要一些同步。类似的东西:

private static Random random;
private static object syncObj = new object();
private static void InitRandomNumber(int seed)
{
     random = new Random(seed);
}
private static int GenerateRandomNumber(int max)
{
     lock(syncObj)
     {
         if (random == null)
             random = new Random(); // Or exception...
         return random.Next(max);
     }
}

答案 1 :(得分:7)

Dilbert在2001年遇到了同样的问题:

http://dilbert.com/strips/comic/2001-10-25/

重合?

我不这么认为。

且random.org同意:http://www.random.org/analysis/

答案 2 :(得分:6)

问题是您每次都在创建一个具有相同种子编号的新Random实例。您应该创建一个Random实例(如果需要,将其存储在静态中)并简单地在同一实例上调用next方法。

随机数生成并非真正随机,有关详细信息,请参阅this Wikipedia entry

答案 3 :(得分:3)

伪随机数生成器通常通过选择种子,然后基于该种子生成确定性序列来工作。每次选择相同的种子,您将生成相同的序列。

.NET中只有“^ 2”个不同的随机序列。

答案 4 :(得分:2)

不确定内部是如何工作的。查看维基,但这很简单。

public class MathCalculations
{
    private Random rnd = new Random();

    public Int32 getRandom(Int32 iMin, Int32 iMax)
    {
        return rnd.Next(iMin, iMax);
    }
}

public class Main
{
    MathCalculations mathCalculations = new MathCalculations();
    for (int i = 0; i < 6; i++)
    {
        getRandom(0,1000);
    }
}

将生成Number1,Number2,Number3,Number4,Number5,Number6(1个种子,1个序列中的多个数字,随机*不是真的,但是大约*)

如果你这样做:

public class MathCalculations
{
    public Int32 getRandom(Int32 iMin, Int32 iMax)
    {  
        Random rnd = new Random();
        return rnd.Next(iMin, iMax);
    }
}

public class Main
{
    MathCalculations mathCalculations = new MathCalculations();
    for (int i = 0; i < 6; i++)
    {
        getRandom(0,1000);
    }
}

现在你将获得Number1,Number1,Number1,Number1,Number1,Number1(1个种子,6个相等的多个序列序列,总是从每个相等的序列中选择相同的起始编号)。在某些时候,Number1会有所不同,因为种子会随着时间的推移而改变..但你需要等待一段时间,但是,你永远不会从序列中选择number2。

原因是,每次生成具有相同种子的新序列时,因此序列一遍又一遍,并且每次随机生成将选择其序列中的第一个数字,其中相同种子,当然总是一样的。

通过随机生成器的基础方法不确定这在技术上是否正确,但这就是它的行为方式。

答案 5 :(得分:0)

如果有人正在寻找“快速而肮脏”的“解决方案”(并且我谨慎使用该术语),那么这对大多数人来说就足够了。

int secondsSinceMidnight = Convert.ToInt32(DateTime.Now.Subtract(DateTime.Today).TotalSeconds);
Random rand = new Random(secondsSinceMidnight); 
var usuallyRandomId = rand.Next();

请注意我的使用通常是随机的。我同意标记为答案的项目是更正确的方法。

答案 6 :(得分:0)

萨拉姆致全部, 嗯它也让我疯了。答案很简单。在随机生成之前更改种子。

实施例: 我想生成1到10之间的随机数

Random rnd = new Random(DateTime.Now.Seconds);
int random_number = rnd.Next(10);

将它放入循环中并运行三次。它会给出低于10的随机数。