【问题标题】:Mono Getting the same sequence using RandomMono 使用 Random 获得相同的序列
【发布时间】:2015-02-08 03:32:38
【问题描述】:

当我在 monodevelop IDE 中的 Mono(显然不是 Microsoft 的 C#)中运行以下代码时。我每次都得到相同的随机数序列(00111111110110001001)。如果我将范围更改为其他内容,例如r.Next(0, 5) 然后我得到随机值。这对我来说似乎很奇怪..这是一个错误还是我在做一些愚蠢的事情?

注意:有时这些数字似乎被否定了......例如我偶尔会看到 11000000001001110110。

using System;

namespace TestRNG
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            Random r = new Random ();
            for (int i = 0; i < 20; i++) {
                Console.Write(r.Next(0, 2));
            }
            Console.WriteLine();
        }
    }
}

这不是“在 Random 实例上调用 Next() 调用过于紧密,因此使用来自系统时钟问题的相同种子作为种子”。

使用以下代码:

using System;

namespace TestRNG
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            Random r = new Random (Guid.NewGuid().ToByteArray()[0]);
            for (int i = 0; i < 20; i++) {
                int rn = r.Next ();
                Console.WriteLine(rn + " " + (rn % 2));
            }
            Console.WriteLine();
        }
    }
}

我看到我每次都得到不同的 rn 值,但我怀疑 r.Next() 返回的 rn % 2 的值序列与我经常看到的旧值相同。这让我相信俄罗斯?之前发布答案并被否决的人是正确的(他随后删除了他的答案)。例如,请参阅http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx

基于下面的其中一个 cmets,这可能只是一个单声道实现的东西。

【问题讨论】:

  • 在 Windows 上运行它会产生不同的零和一序列。
  • 每次都会这样吗? (即,您每次跑步时它们是否不同?)。您是使用单声道还是 C# 运行。在单声道中可能是一个糟糕的 RNG 实现?
  • 不,我们的俄罗斯朋友错了。当您取模 2 时,该序列显然不是随机的。换句话说,r.Next() 为您提供了一个随机的位序列,除了最后一位 - 最后一位始终是可预测的。这似乎是一个单声道实现问题,并且代码在 Windows 中很好。
  • 我已将其从 C# 重新标记为 mono 并修复了标题,因此我不会混淆 C# 的人。我还向 mono 发布了错误报告。我认为我们的俄罗斯朋友的观点是生成的随机数的低位缺乏随机性。我怀疑这可能是这里的原因。实际上,如果我们的俄罗斯朋友使用模数,您可能是对的,但这无济于事(我不记得他的名字或他发布的确切文字)。右移似乎确实有帮助。
  • 您应该重新添加 [c#] 标签 - 只是因为它是 [mono] 并不意味着它不是 [c#]。 [mono]只是CLR的linux实现,其中包括[c#]。

标签: c# delegates mono


【解决方案1】:

好吧,扩展 swistak 所说的内容(因为我也使用了 Guid 类),这是我为您的问题编写的代码,已经过测试并且可以工作:

using System;
using System.Linq;

namespace pruebaDeNumerosAleatorios
{
class MainClass
{
    public static int RandomNumber()
    {
        Random x = new Random(Guid.NewGuid().ToByteArray().First());
        return x.Next(0, 20);
    }
    public static void Main(string[] args)
    {
        for (int i = 0; i < 20; i++)
            Console.WriteLine(RandomNumber());
    }

}
}

正如之前所说,您不会将时间分配给内部时钟(您将其用作种子)在迭代之间进行更改,因此生成的数字是相同的。我在这里所做的是实现生成“唯一”数字的 Guid 类,将其转换为字节数组,并将数组的第一个元素用作种子。 我在一个方法中这样做是因为这样可以保证每次调用该方法时 Guid 类都会生成一个不同的数字,所以我使用不同的种子作为随机数。

【讨论】:

  • 您每次都在创建一个新的随机数。我不相信这不是它应该使用的方式。
  • 是的,但在内存方面不会影响,因为随机对象的范围是我创建它们的方法。
  • 返回随机值后,创建的对象对垃圾收集器来说是合法的。
  • 而且,如果您的问题确实是 monoDevelop 问题,这至少可以作为“解决方法”:)
  • 这一切都是真的。但是您有分配和释放大量随机对象的时间开销。它做的工作比它需要的要多。 (这不是一个单一开发的错误。可能是一个单一的错误)。
【解决方案2】:

您可以使用Guid 类生成“更随机”的数字,而不会对性能产生更大的影响:

Random r = new Random(Guid.NewGuid().ToByteArray()[0]);

编辑:每次获取相似值的问题是因为Random.Next() 从当前系统时钟获取值,因此每次编译之间可能没有太大的时间差异来生成不同的值。尝试在循环中运行您的代码,值应该更加多样化。

【讨论】:

  • 这不是比以前“更多”的随机性。这只是一颗不同的种子。随机数生成器没有改变。
  • 我使用这个种子得到的字符串与隐式系统时间种子不同。但它仍然重复不同的迭代。这就是我对挑选不同种子的期望。
  • 但是通过随机选择种子,每次都可以获得不同的值。我的例子不能解决这个问题吗?
  • @swistak - 不,它没有。 OP 明确表示这不是种子问题。这似乎是一个单声道实现问题,因为 OP 的代码在 Windows 中运行良好。
  • Random.Next() 从系统时钟中获取其值。如果您使用默认构造函数实例化Random,它将从系统时钟获取种子。从那时起,产生的值是确定性的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 2019-12-31
  • 2014-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多