【问题标题】:Random number generation in C#C#中的随机数生成
【发布时间】:2010-11-29 02:21:55
【问题描述】:

我一直在为训练练习编写一些 C# 代码,其中我必须创建一个随机矩形数组。

问题是我的 GetRandomRectangle 函数生成的矩形总是相同的。 我使用System.Random 来生成矩形的坐标。

我意识到这是因为 Random 对象是使用默认构造函数创建的,因此具有相同的种子。我已经对其进行了修改,现在为每个矩形获取不同的种子,并且效果很好。

问题是 - 它如何决定“默认种子”?我注意到它似乎也不会随着时间而改变,使用种子 2 创建的矩形将始终具有相同的尺寸。

这可能是我可以用谷歌搜索的东西,但也很高兴听到你们的意见和信息。

谢谢:)

【问题讨论】:

  • 它如何决定默认种子?不是随机根据你的发现! - 当然,没有随机的东西,但这是一个完全不同的讨论。
  • 我知道这个问题,并且不觉得它是重复的。该用户想知道为什么他们的代码不起作用。我知道这是因为种子,并且想更多地了解随机数生成中使用的机制。

标签: c# random


【解决方案1】:

默认种子取自系统时钟。

我猜你的GetRandomRectangle 方法被快速连续调用并且每次都实例化一个Random 的新实例。当您这样做时,Random 的每个实例都会从系统时钟中获取相同的种子,这就是您的方法每次都创建相同矩形的原因。

一种解决方案是创建Random一个实例并将其传递到您的方法中:

Random rng = new Random();

Rectangle foo = GetRandomRectangle(rng);
Rectangle bar = GetRandomRectangle(rng);
Rectangle baz = GetRandomRectangle(rng);

// ...

public Rectangle GetRandomRectangle(Random rng)
{
    // create the rectangle using rng
}

【讨论】:

  • 即使我这样做了,我运行我的程序,然后关闭它,然后在其间几秒钟再次运行它,它似乎产生了相同的矩形集。有趣...
  • 因为它使用时间戳作为种子。它应该使用 tickcount 来保证不会得到相同的种子。
  • @cemkalyoncu:默认的Random 构造函数使用Environment.TickCount 作为种子。我认为这不是问题所在。
【解决方案2】:

实际上,默认的Random() 构造函数是依赖于时间的,并且应该在第二次运行应用程序时提供不同的输出。如果您每次都得到相同的矩形,那么一定是发生了其他事情。

手动提供种子将始终为您提供相同的伪随机数序列。

您应该只需要实例化一个 Random 对象即可生成所有随机数。不要为每个矩形创建一个新实例。

【讨论】:

  • @Thorarin:如果您快速连续创建多个Random 实例(例如,在紧密循环中),那么它们将使用相同的种子:在这种情况下,系统时钟不会很快滴答作响足以为每个实例提供唯一值。
  • @Luke:因此我对使用单个实例的评论。
【解决方案3】:

我曾经也使用过它,但我发现该类产生的随机值远远不够。我改为切换到密码学命名空间中的随机函数。这是一个非常简单的版本,没有错误检查或屏幕尺寸转换:

     byte[] randomBytes = new byte[4];
     RandomNumberGenerator numberGenerator = System.Security.Cryptography.RandomNumberGenerator.Create();
     numberGenerator.GetNonZeroBytes(randomBytes);
     int x = randomBytes[0];
     int y = randomBytes[1];
     int width = randomBytes[2];
     int height = randomBytes[3];
     System.Drawing.Rectangle block = new Rectangle(x, y, width, height);

【讨论】:

  • Random 类生成的随机数足以满足大多数用途,如果您正确使用它的话。仅当您需要非常好的随机性时才需要密码随机生成器,例如创建加密密钥。
【解决方案4】:

当您使用种子时,这意味着您想要从该种子开始的相同序列

试试没有种子的构造函数

【讨论】:

    【解决方案5】:

    我不是 C# 专家,但这可能有用。

     public Rectangle GetRandomRectangle()
     {
          static Random rng=new Random();
          // create the rectangle using rng
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-18
      • 2015-07-19
      • 1970-01-01
      • 2019-05-15
      • 1970-01-01
      相关资源
      最近更新 更多