关于c#:为什么Random.Next()总是返回相同的数字

Why does Random.Next() always return the same number

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

考虑这种方法:

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

在我的机器上,执行这个循环会通过1500次迭代产生相同的数字:

1
2
3
4
5
6
  for (int i = 0; i < 1501; i++)
            {
                int random = GenerateRandomNumber(100000000, 999999999);
                Console.WriteLine(random.ToString());
                Console.ReadKey();
            }

每次迭代我都得到145156561。

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


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

如果您希望有一个静态的、随机的数字生成来产生不同的结果,那么您应该稍微修改一下。然而,由于random不是threadsafe,所以静态使用时需要一些同步。类似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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);
     }
}


迪尔伯特在2001年也遇到了同样的问题:

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

巧合?

我不这么认为。

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


问题是,您每次都要创建一个具有相同种子数的新随机实例。您应该创建一个单独的随机实例(如有必要,将其存储在静态实例中),并简单地在同一个实例上调用下一个方法。

随机数生成并不是真正随机的,有关更多详细信息,请参阅此维基百科条目。


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

.NET中有"only"2^32个不同的随机序列。


不知道内部是如何工作的。在wiki上查一下,但很简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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);
    }
}

将生成数字1、数字2、数字3、数字4、数字5、数字6(1个种子,1个多数字序列,随机*不是真的,而是大约*)

但是,如果您这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
    }
}

现在您将得到数字1、数字1、数字1、数字1、数字1(1个种子,6个相等的数字序列,总是从每个相等的序列中选择相同的起始数字)。在某个时刻,数字1会有所不同,因为种子会随着时间的推移而改变。但是你需要等待一段时间,尽管如此,你永远不会从序列中选择数字2。

原因是,每次使用相同的种子生成一个新序列时,序列都是相同的,因此每次随机生成的序列都会选择其序列中的第一个数字,而使用相同的种子,当然总是相同的。

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


萨拉姆对所有人,这也让我发疯了。答案很简单。在随机生成之前更改种子。

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

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

把它放进一个循环里,运行三次。它会给出10以下的随机数。


如果任何人都在寻找"快速而肮脏的"解决方案(我谨慎地使用这个术语),那么这对大多数人来说就足够了。

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

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