【问题标题】:Reinventing The Wheel: Random Number Generator重新发明轮子:随机数生成器
【发布时间】:2011-08-16 15:06:51
【问题描述】:

所以我是 C++ 新手,正在尝试学习一些东西。因此,我正在尝试制作一个随机数生成器(如果您愿意,可以使用 RNG 或 PRNG)。我有 RNG 的基本知识,比如你必须从种子开始,然后通过算法发送种子。我坚持的是人们如何提出上述算法。

这是获取种子的代码。

int getSeed()
{
    time_t randSeed;
    randSeed = time(NULL);
    return randSeed;
}

现在我知道在 C++ 中有预构建的 RNG,但我希望学习的不仅仅是复制其他人的工作并尝试弄清楚。

因此,如果有人能将我带到我可以阅读的地方或向我展示如何为此提出算法的示例,我将不胜感激。

【问题讨论】:

  • 你读过这篇文章吗? gnu.org/software/gsl/manual/html_node/…
  • PRNG 的设计与语言无关,与数论和代数有关,而不是编程。如果您的目标是通过一些示例来学习 C++,那么您应该寻找不同的东西。如果你想了解 PRNG 设计,你应该删除提到 C++ 的部分。
  • @Seth Carnegie 我读过那篇文章,但我无法真正理解它想要表达的意思。
  • @Cistoran:了解什么是好的 RNG 需要大量的数学知识;统计学、数论、群论等(其中大部分超出了我的知识和耐心水平)。这不是我建议你随便进入的那种事情。考虑到正如您所说,这将是重新发明轮子,因此还有更多值得学习的东西。
  • 有几个人略微不鼓励这种追求。我说去吧。无论您感兴趣的领域是什么,请关注它。不要让人们说它不实用打扰你——它可能不实用,但它应该是有教育意义的。随机数会带你进入许多程序员从未涉足的领域——小游戏、数论、统计——所有这些都值得学习。

标签: c++ algorithm random numbers seed


【解决方案1】:

首先,澄清一下,您提出的任何算法都是伪随机数生成器,而不是真正的随机数生成器。由于您将创建一个算法(即编写一个函数,即制定一组规则),随机数生成器最终将不得不重复自身或执行类似的非随机操作。

真正随机数生成器的示例是从自然界捕获随机噪声并将其数字化。其中包括:

http://www.fourmilab.ch/hotbits/

http://www.random.org/

您还可以购买产生白噪声(或其他一些随机方式)的物理设备并以数字方式捕获它:

http://www.lavarnd.org/

http://www.idquantique.com/true-random-number-generator/products-overview.html

http://www.araneus.fi/products-alea-eng.html

就伪随机数生成器而言,最容易学习的(以及普通外行可能自己制作的)是linear congruential generators。不幸的是,这些也是一些最糟糕的 PRNG。

确定什么是好的 PRNG 的一些准则包括:

  1. 周期性(可用数字的范围是多少?)
  2. 连续数字(同一个数字连续重复两次的概率是多少)
  3. 一致性(从某个子范围中选取数字的可能性是否与从另一个子范围中选取数字的可能性一样)
  4. 难以对其进行逆向工程(如果它接近于真正随机,那么有人应该无法根据它生成的最后几个数字找出它生成的下一个数字)
  5. 速度(我能以多快的速度生成一个新数字?需要 5 次还是 500 次算术运算)
  6. 我确定我还缺少其他人

Mersenne Twister 是目前在大多数应用程序(即不是 crptography)中被认为很好的比较流行的一个。从链接可以看出,它是一个简单的算法,可能只有 30 行代码。然而,试图从头开始编写那 20 或 30 行代码需要大量的脑力和对 PRNG 的研究。通常最著名的算法是由研究 PRNG 数十年的教授或行业专业人士设计的。

我希望你学习 PRNG 并尝试自己动手(尝试 Knuth 的计算机编程艺术或数字食谱作为起点),但我只是想在一天结束时把这一切都说清楚(除非 PRNG将是你一生的工作)最好只使用别人想出的东西。另外,沿着这些思路,我想指出历史上的编译器、电子表格等不使用大多数数学家认为好的 PRNG,所以如果您需要高质量的 PRNG,请不要使用标准库之一在 C++、Excel、.NET、Java 等中,直到你研究了它们是用什么实现的。

【讨论】:

  • 关于“逆向工程的困难”:这是加密安全 PRNG 的一个问题,但对于一般的 PRNG 来说不是。 PRNG 的典型用途是为计算机游戏或蒙特卡洛模拟添加一点随机性。此类应用程序不需要安全的 PRNG。 OTOH,如果您使用 PRNG 来加密消息或数字签名,那么对逆向工程的担忧就会上升到最前沿。
【解决方案2】:

线性同余生成器是常用的,Wiki article 很好地解释了它。

【讨论】:

  • 并非如此。特别是,它说“最有效的 LCG 的 m 等于 2 的幂,通常是 m = 2^32 或 m = 2^64。”已经证明,当m 是 2 的幂时,您无法获得好的生成器; m 应该是素数。线性同余生成器的参考资料是“随机数生成器:很难找到好的”,Park 和 Miller,CACM 1988 年 10 月。
  • @James Wikipedia 的奇妙之处在于,像您这样的用户可以编辑和改进它。另外,请注意它说的是“高效”,而不是“好”。如果你想要一个好的 PRNG,你根本不应该使用 LCG。
【解决方案3】:

引用约翰·冯·诺依曼的话:

任何考虑算术的人 产生随机数字的方法是 当然是在犯罪的状态。

这摘自 Knuth 的书“计算机编程的艺术”的第 3 章随机数,它必须是对该主题的最详尽概述。而一旦你读过它,你会筋疲力尽。您还将知道为什么不想编写自己的随机数生成器。

【讨论】:

    【解决方案4】:

    正确的解决方案最能满足要求,并且每种情况的要求都是独一无二的。这可能是最简单的方法:

    • 创建一个大的一维数组 填充“真实”随机值。
    • “种子”你的伪随机生成器 计算起始索引 系统时间。
    • 遍历数组并返回 每次致电您的价值 功能。
    • 到达终点时绕一圈。

    【讨论】:

      猜你喜欢
      • 2014-11-20
      • 1970-01-01
      • 2013-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 2012-11-26
      相关资源
      最近更新 更多