C# 系统随机不那么随机,为什么会发生这种情况?
可能重复:C# 系统随机不那么随机,为什么会发生这种情况?,c#,C#,可能重复: 我已将在更大系统中观察到的行为提炼为以下代码序列: for (int i = 0; i < 100; i++) { Random globalRand = new Random(0x3039 + i); globalRand.Next(); globalRand.Next(); int newSeed = globalRand.Next(); Random rand = new Random(newSeed); int va
我已将在更大系统中观察到的行为提炼为以下代码序列:
for (int i = 0; i < 100; i++)
{
Random globalRand = new Random(0x3039 + i);
globalRand.Next();
globalRand.Next();
int newSeed = globalRand.Next();
Random rand = new Random(newSeed);
int value = rand.Next(1, 511);
Console.WriteLine(value);
}
for(int i=0;i<100;i++)
{
随机全局随机=新随机(0x3039+i);
globalRand.Next();
globalRand.Next();
int newSeed=globalRand.Next();
Random rand=新随机(newSeed);
int值=rand.Next(1511);
控制台写入线(值);
}
从Visual Studio 2012 targeting.NET 4.5运行此命令将输出316或315。把这个扩展到100次迭代之后,你会看到值缓慢递减(314, 313…),但它并不是我想象的任何人会认为“随机”。
编辑
我知道关于StackOverflow已经有几个问题问了为什么他们的随机数不是随机的。但是,这些问题有以下两个方面的问题:a)没有向随机对象实例传递种子(或传递相同的种子);b)执行类似于
NextInt(0,1)
的操作,并且没有意识到第二个参数是排他边界。对于这个问题,这两个问题都不成立。这是一个伪随机生成器,基本上创建了一个长(无限)数字列表。列表是确定的,但在大多数实际场景中,顺序可以被视为随机的。然而,顺序是由种子决定的
您可以实现的最随机的行为(如果没有始终很难正确使用的花哨技巧)是反复重用同一对象
如果您将代码更改为下面的值,则会出现更随机的行为
Random globalRand = new Random();
for (int i = 0; i < 100; i++)
{
globalRand.Next();
globalRand.Next();
int newSeed = globalRand.Next();
Random rand = new Random(newSeed);
int value = rand.Next(1, 511);
Console.WriteLine(value);
}
Random globalRand=new Random();
对于(int i=0;i<100;i++)
{
globalRand.Next();
globalRand.Next();
int newSeed=globalRand.Next();
Random rand=新随机(newSeed);
int值=rand.Next(1511);
控制台写入线(值);
}
原因是伪随机生成器背后的数学原理基本上只是创建了一个无限的数字列表
这些数字的分布几乎是随机的,但它们出现的顺序却不是。计算机是确定性的,因此不能产生真正的随机数(没有帮助),因此为了避免这种情况,数学天才们已经产生了能够产生这些数字列表的函数,这些函数有很多随机性,但种子决定了顺序
给定相同的种子,函数总是产生相同的顺序。如果在每个顺序附近有两个种子(close可以是使用哪个函数的属性),列表中的前几个数字几乎相同,但最终会非常不同。这是一个伪随机生成器,基本上创建了一个长(无限)数字列表。列表是确定的,但在大多数实际场景中,顺序可以被视为随机的。然而,顺序是由种子决定的 您可以实现的最随机的行为(如果没有始终很难正确使用的花哨技巧)是反复重用同一对象 如果您将代码更改为下面的值,则会出现更随机的行为
Random globalRand = new Random();
for (int i = 0; i < 100; i++)
{
globalRand.Next();
globalRand.Next();
int newSeed = globalRand.Next();
Random rand = new Random(newSeed);
int value = rand.Next(1, 511);
Console.WriteLine(value);
}
Random globalRand=new Random();
对于(int i=0;i<100;i++)
{
globalRand.Next();
globalRand.Next();
int newSeed=globalRand.Next();
Random rand=新随机(newSeed);
int值=rand.Next(1511);
控制台写入线(值);
}
原因是伪随机生成器背后的数学原理基本上只是创建了一个无限的数字列表
这些数字的分布几乎是随机的,但它们出现的顺序却不是。计算机是确定性的,因此不能产生真正的随机数(没有帮助),因此为了避免这种情况,数学天才们已经产生了能够产生这些数字列表的函数,这些函数有很多随机性,但种子决定了顺序
给定相同的种子,函数总是产生相同的顺序。如果在每个顺序附近有两个种子(close可以是使用函数的属性),则列表中的前几个数字几乎相同,但最终会非常不同。使用第一个随机数生成第二个。不会让它变得更“随机”。按照建议,试试这个 同样,正如建议的那样,不需要在循环中生成随机对象
Random globalRand = new Random();
for (int i = 0; i < 100; i++)
{
int value = globalRand.Next(1, 511);
Console.WriteLine(value);
}
Random globalRand=new Random();
对于(int i=0;i<100;i++)
{
int value=globalRand.Next(1511);
控制台写入线(值);
}
使用第一个随机数生成第二个随机数。不会让它变得更“随机”。按照建议,试试这个
同样,正如建议的那样,不需要在循环中生成随机对象
Random globalRand = new Random();
for (int i = 0; i < 100; i++)
{
int value = globalRand.Next(1, 511);
Console.WriteLine(value);
}
Random globalRand=new Random();
对于(int i=0;i<100;i++)
{
int value=globalRand.Next(1511);
控制台写入线(值);
}
没有参数,Random c'tor将当前日期和时间作为种子-通常,在内部计时器确定当前日期和时间已更改之前,您可以执行相当数量的代码。因此,您反复使用同一种子,并反复获得相同的结果。
来源:不带参数的Random c'tor将当前日期和时间作为种子-通常,在内部计时器确定当前日期和时间已更改之前,您可以执行大量代码。因此,您反复使用同一种子,并反复获得相同的结果。 来源:我相信
Random()
是基于时间的,因此如果您的流程运行非常快,那么如果您在循环中不断创建Random()
的新实例,您将得到相同的答案。尝试在循环之外创建Random()
,只需使用.Next()
即可获得如下答案:
Random rand = new Random();
for (int i = 0; i < 100; i++)
{
int value = rand.Next();
Console.WriteLine(value);
}
Random rand=新Rando