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

发布于 2024-10-21 07:10:25 字数 559 浏览 6 评论 0原文

考虑这个方法:

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) 说“返回小于指定最大值的非负随机数。也许我不理解一些基本的东西。

Consider this method:

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

On my machine, executing this loop yields the same number through 1500 iterations:

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

I get 145156561, for every single iteration.

I don't have a pressing issue, I was just curious about this behavior because .Next(max) says "Returns a Non Negative random number less than the specified maximum. Perhaps I am not understanding something basic.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

天生の放荡 2024-10-28 07:10:25

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

如果您想要产生不同结果的静态随机数,则应该稍微修改一下。但是,由于 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);
     }
}

You're always seeding a new instance with the same seed, and then grabbing the first max. By using a Seed, you're guaranteeing the same results.

If you want to have a static, random number generation that does different results, you should rework this a bit. However, since Random is not threadsafe, it requires some synchronization when used statically. Something like:

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);
     }
}
乖乖哒 2024-10-28 07:10:25

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

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

巧合?

我不这么认为。

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

Dilbert has encountered the same problem back in 2001:

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

Coincidence?

I don't think so.

And random.org agrees : http://www.random.org/analysis/

亢潮 2024-10-28 07:10:25

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

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

The problem is that you are creating a new Random instance with the same seed number each time. You should create a single Random instance (store it in a static if necessary) and simply call the next method on that same instance.

Random number generation is not truly random, see this Wikipedia entry for more details.

叹梦 2024-10-28 07:10:25

祝大家,
好吧,这也让我发疯了。答案很简单。在生成随机数之前更改种子。

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

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

将其放入循环中并运行 3 次。它将给出 10 以下的随机数。

Salam to All,
Well it drove me crazy as well. The answer is simple. Change the seed before you generate random.

Example:
I want to generate random number between 1 to 10

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

Put it inside a loop and run it three times. It will give out random numbers below 10.

独闯女儿国 2024-10-28 07:10:25

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

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

Pseudo-random number generator usually work by choosing a seed, and then generating a deterministic sequence based on that seed. Choosing the same seed every time, you generate the same sequence.

There are "only" 2^32 different random sequences in .NET.

情丝乱 2024-10-28 07:10:25

不确定内部结构是如何工作的..检查维基百科,但它非常简单。

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。

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

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

Not sure how the internals work.. check wiki for it, but it's very simple.

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);
    }
}

will generate Number1, Number2, Number3, Number4, Number5, Number6 (1 seed, 1 sequence of many numbers, random*not really, but approx.*)

if you however do this:

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);
    }
}

You will now get Number1, Number1, Number1, Number1, Number1, Number1 (1 seed, 6 equal sequences of many numbers, always pick the same starting number from each equal sequence).. At some point Number1 will be different, because the seed changes over time.. but you need to wait some time for this, nonetheless, you never pick number2 from the sequence.

The reason is, each time you generate a new sequence with the same seed, hence the sequence is the same over and over again, and each time your random generated will pick the first number in it's sequence, which, with the same seed, is of course always the same.

Not sure if this is technically correct by the underlying methods of the random generator, but that's how it behaves.

-柠檬树下少年和吉他 2024-10-28 07:10:25

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

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

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

In the event that anyone is looking for a "quick and dirty" "solution" (and I use that term with caution) then this will suffice for most.

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

Please note my use of usually random. I agree that the item marked as the answer is a more correct way of doing this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文