【问题标题】:more than 1 sequence of random numbers c#, linq超过1个随机数序列c#,linq
【发布时间】:2010-12-04 12:57:27
【问题描述】:

我正在使用此代码生成随机数字序列:

var sequence = Enumerable.Range(0, 9).OrderBy(n => n * n * (new Random()).Next());

在我需要多个序列之前一切正常,在这段代码中我调用了 10 次例程,结果是我的问题,所有序列都是相等的。

        int i = 0;
        while (i<10)
        {
            Console.Write("{0}:",i);
            var sequence = Enumerable.Range(0, 9).OrderBy(n => n * n * (new Random()).Next());
            sequence.ToList().ForEach(x=> Console.Write(x));
            i++;
            Console.WriteLine();
        }

有人可以告诉我如何实际生成不同的序列吗?希望使用 LINQ

【问题讨论】:

  • 如果OrderBy 确实多次调用键选择器(我在文档中没有找到关于是否保证只调用一次的任何内容)您的代码将出现错误,因为那时比较器合同将是违反了。

标签: c# linq random sequence


【解决方案1】:

问题是您在每次迭代中都创建了一个 Random 的新实例。每个实例将从当前时间获取其初始种子,与您的委托执行频率相比,该种子的变化相对较少。您可以创建Random单个 实例并重复使用它。更多详情请查看我的article on randomness

但是,我还建议您使用 Fisher-Yates shuffle 而不是 OrderBy 来洗牌(Stack Overflow 上有很多示例,例如 this one)......虽然它看起来像你试图在某种程度上偏向随机性。如果您能提供更多确切您正在尝试做什么的详细信息,我们或许可以提供更多帮助。

【讨论】:

  • 嗨,乔恩,我正在为遗传算法创建个体。我测试了这个序列生成器绘制结果点的好处(使用一个点,下一个点在矩形中具有坐标 x ,y )。结果很好,我在图片中看不到任何图案。我正在阅读有关种子值的信息。如果我在代码中添加“i”作为种子,那么所有的序列都是不同的,这样可以吗?种子必须有一些额外的属性?
  • @voodoomsr:这取决于你是否希望它是可预测的——如果你需要不可预测性,你也需要一个不可预测的种子。如果每次都传入相同的种子,那么每次都会得到相同的结果。
  • mmm 如果我创建一个实际上是其他随机数的种子,我会得到不同的结果,我认为这可能足够不可预测。我将进一步研究 Fisher-Yates 算法。乍一看,实施起来并不难
  • @voodoomsr:如果您查看第二段中的第二个链接,您会看到一个现有的实现。
【解决方案2】:

您正在快速连续创建 10 个 Random 实例,并从每个实例中提取第一个伪随机数。我并不惊讶他们都是一样的。

试试这个:

Random r = new Random();
var sequence = Enumerable.Range(0, 9).OrderBy(n => n * n * r.Next());

【讨论】:

    【解决方案3】:

    在我的代码中,我使用了多年前写的这个静态方法,它仍然显示出很好的随机化:

    using System.Security.Cryptography;
    ...
    
    public static int GenerateRandomInt(int from, int to)
    {
      byte[] salt = new byte[4];
      RandomNumberGenerator rng = RandomNumberGenerator.Create();
      rng.GetBytes(salt);
      int num = 0;
      for (int i = 0; i < 4; i++)
      {
        num += salt[i];
      }
      return num % (to + 1 - from) + from;
    }
    

    无法详细解释这个例子,我需要及时把自己带回来记住,但我不在乎;)

    【讨论】:

    • 如果你想要一个大于 1024 的数字,它不会有太大用处,是吗?如果你要求(比如说)1-700,你会发现它并没有很好的分布。此外,每次都创建一个新的随机数生成器并不是一个好主意。如果你真的需要加密安全的随机数,最好有一个 Random 的子类,它委托给 RandomNumberGenerator 的一个实例。否则,只需使用随机。
    • 给谁投了-1票:你试过这个代码吗?把开玩笑式的回答和对问题的误解分开
    • @Jon Skeet,1)它通过稍微修改代码实现了良好的分发(将答案视为一个想法,而不是一个指令)。 2) 为什么创建 randomnumbergen 不是一个好主意?表现?谁在乎这个问题? 3) 来自 cryptographic 的 RandomNumberGenerator 和来自 System 的 Random 是不同的类,具有非常不同的实现
    • @Genius:我是这个代码的反对者,因为它是糟糕的代码。 1) 对于任何稍微大一点的数字,它都有一个 terrible 分布。 2) RNG 的部分point 是您可以继续重用同一个实例。为什么要反对成语? 3) 是的,我知道它们非常不同。但是您可以覆盖 Random 中的适当方法,以将 Random 的便捷 API 置于 RandomNumberGenerator 的加密安全随机性之上。
    • @Jon Skeet,从未将这种方法用于大量数据。 mb 你是对的——对于大量的人来说,这种方法没有用,但作者对此只字未提。 P.S.:我认为投票是针对完全不正确的答案,但不是仅仅“我不同意这种观点”。
    猜你喜欢
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 2012-10-23
    • 2016-06-12
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    • 2014-06-14
    相关资源
    最近更新 更多