【问题标题】:Random encounter not so random随机的相遇不是那么随机
【发布时间】:2010-04-28 07:33:08
【问题描述】:

您好,我在使用 C# 生成随机数时遇到了一些问题 现在我有了这个功能。

public Color getRandomColor()
{
    Color1 = new Random().Next(new Random().Next(0, 100), new Random().Next(200, 255));
    Color2 = new Random().Next(new Random().Next(0, 100), new Random().Next(200, 255));
    Color3 = new Random().Next(new Random().Next(0, 100), new Random().Next(200, 255));
    Color color = Color.FromArgb(Color1, Color2, Color3);
    Console.WriteLine("R: " + Color1 + " G: " + Color2 + " B: " + Color3 + " = " + color.Name);
    return color;
}

现在你可能会注意到那里有很多 new Random(),那是因为我想排除它可能是同一个实例错误的可能性。

我现在运行这个函数 8 次,几次。 现在这里是输出。

R: 65 G: 65 B: 65 = ff414141
R: 242 G: 242 B: 242 = fff2f2f2
R: 205 G: 205 B: 205 = ffcdcdcd
R: 40 G: 40 B: 40 = ff282828
R: 249 G: 249 B: 249 = fff9f9f9
R: 249 G: 249 B: 249 = fff9f9f9
R: 94 G: 94 B: 94 = ff5e5e5e
R: 186 G: 186 B: 186 = ffbababa

R: 142 G: 142 B: 142 = ff8e8e8e
R: 190 G: 190 B: 190 = ffbebebe
R: 19 G: 19 B: 19 = ff131313
R: 119 G: 119 B: 119 = ff777777
R: 119 G: 119 B: 119 = ff777777
R: 75 G: 75 B: 75 = ff4b4b4b
R: 169 G: 169 B: 169 = ffa9a9a9
R: 127 G: 127 B: 127 = ff7f7f7f

R: 73 G: 73 B: 73 = ff494949
R: 27 G: 27 B: 27 = ff1b1b1b
R: 125 G: 125 B: 125 = ff7d7d7d
R: 212 G: 212 B: 212 = ffd4d4d4
R: 174 G: 174 B: 174 = ffaeaeae
R: 0 G: 0 B: 0 = ff000000
R: 0 G: 0 B: 0 = ff000000
R: 220 G: 220 B: 220 = ffdcdcdc

如您所见,这又不是那么随机了,但为什么会发生这种情况呢?我该如何应对?

【问题讨论】:

  • 我在标准化范围内生成随机颜色时遇到了同样的问题。一种不提供种子的快速方法是使用相同的随机流将几个值排列在一起。缺乏精度,但可用于获得稍微多样化的随机分布。例如。 int x = rng.Next() ^ rng.Next();整数幅值 = x * x;浮点值 = x / (float)magnitude;
  • 使用此方法,您可以通过以下方式生成稍微更好的颜色分布。颜色 = 颜色 = 新颜色((字节)(rand.Next(0, 255)^ rand.Next(0, 255)),(字节)(rand.Next(0, 255)^ rand.Next(0, 255) )), (byte)(rand.Next(0, 255) ^ rand.Next(0, 255)), (byte)(rand.Next(0, 255) ^ rand.Next(0, 255)))

标签: c# random


【解决方案1】:

您正在为您需要的每个值创建一个新的Random

尝试创建一个唯一的Random 对象并多次调用.Next() 函数。

public Color getRandomColor()
{
    Random rand = new Random();

    Color1 = rand.Next(rand.Next(0, 100), rand.Next(200, 255));
    Color2 = rand.Next(rand.Next(0, 100), rand.Next(200, 255));
    Color3 = rand.Next(rand.Next(0, 100), rand.Next(200, 255));
    Color color = Color.FromArgb(Color1, Color2, Color3);
    Console.WriteLine("R: " + Color1 + " G: " + Color2 + " B: " + Color3 + " = " + color.Name);
    return color;
}

取自MSDN documentation on Random object

默认情况下,Random类的无参构造函数使用系统时钟生成其种子值,而其有参构造函数可以根据当前时间的滴答数取一个Int32值。然而,由于时钟的分辨率是有限的,使用无参数构造函数来创建不同的 Random 对象会创建随机数生成器,这些生成器会生成相同的随机数序列

【讨论】:

  • 是的,这就是答案。一个接一个地快速创建的 Random 实例倾向于给出相同的值。我认为这是因为它们是由计算机时钟播种的,但这只不过是一种疯狂的猜想。
  • 没错。 Random 有 2 个构造函数。无参数的使用当前时间作为种子。您也可以使用带整数的那个。所以它会使用你传递的参数作为种子。
  • 我的代码在开始时看起来像这样,我们创建了许多实例以查看该帮助程序。但现在我们得到 R: 164 G: 78 B: 145 = ffa44e91 R: 206 G: 20 B: 149 = ffce1495 R: 206 G: 20 B: 149 = ffce1495 R: 73 G: 60 B: 94 = ff493c5e R: 147 G: 94 B: 101 = ff935e65 R: 212 G: 123 B: 61 = ffd47b3d R: 98 G: 79 B: 70 = ff624f46 R: 85 G: 110 B: 79 = ff556e4f如果您看到结果 2 和 3,它们是否相同。
  • 嘿嘿好的,我现在已经将它创建为使用的静态变量。现在这项工作,感谢 static Random random = new Random();诠释颜色1,颜色2,颜色3;公共颜色 getRandomColor() { Color1 = random.Next(0, 255); Color2 = random.Next(0, 255); Color3 = random.Next(0, 255);颜色颜色 = Color.FromArgb(Color1, Color2, Color3); Console.WriteLine("R: " + Color1 + " G: " + Color2 + " B: " + Color3 + " = " + color.Name);返回颜色; }
  • 查看我编辑的答案,对每个 Random 实例使用不同的种子。
【解决方案2】:

每个new Random() 都是seeded with the current time

如果您连续快速创建多个 Random 实例,并且您的机器运行速度足够快,以至于它们足够接近以获得相同的种子,它们将返回相同的值序列!

使用单个Random,调用.Next() 来获取每个值。

现在你可能会注意到有 那里有很多新的 Random(),也就是说 因为我想淘汰 可能相同的概率 实例错误。

这是一个谬误;来自单个Random 的数字流均匀分布 - 努力使其随机化。

【讨论】:

    【解决方案3】:

    您正在按顺序创建许多 Random 对象,这会导致它们使用相同/几乎相同的时间戳播种。从而生成随机数,但它们之间相等。

    尝试创建一个 Random 实例并将其用于您的所有 Random 数需求。

    【讨论】:

      【解决方案4】:

      Random 在使用它的一个实例时效果更好。

      试试这个:

      public Color getRandomColor()
      {
          var random = new Random();
          Color1 = random.Next(random.Next(0, 100), random.Next(200, 255));
          Color2 = random.Next(random.Next(0, 100), random.Next(200, 255));
          Color3 = random.Next(random.Next(0, 100), random.Next(200, 255));
          Color color = Color.FromArgb(Color1, Color2, Color3);
          Console.WriteLine("R: " + Color1 + " G: " + Color2 + " B: " + Color3 + " = " + color.Name);
          return color;
      }
      

      【讨论】:

      • 编辑比使用单个随机要慢吗?它肯定不是“更随机”?
      • 它甚至会在每次调用函数时返回相同的“随机”颜色。
      猜你喜欢
      • 2012-04-24
      • 2011-05-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-01
      • 2012-10-04
      • 1970-01-01
      • 2011-11-07
      • 1970-01-01
      相关资源
      最近更新 更多