【问题标题】:C rand() slightly biasedC rand() 略有偏差
【发布时间】:2021-08-06 23:30:35
【问题描述】:

我正在使用标准 c 库中的 rand() 函数为蒙特卡罗模拟生成 0 到 1 范围内的数字:

(double)rand()/RAND_MAX

但我注意到结果略有偏差。我检查了生成的数字平均在哪个值,它略低于预期的 0.5。

我读到 rand() 是模数偏向的,但我在这里没有使用模数。有没有更精确的方法来生成 1 到 0 之间的数字?

编辑: 我对 Prngs 还很陌生,所以我不知道有些 prngs 不是线程安全的。我应该提到我使用了 rand() 多线程。 无论如何,您的回答帮助我找到了更快且线程安全的 rng。

【问题讨论】:

  • 即使在理想情况下,恰好达到 0.5 的可能性也不大,多少个数字会相差多少?
  • 在十亿次以上的迭代中,它的平均值约为 0.495,以我的结果显着偏向为准。经过更多研究后,如果在欧洲核子研究中心的 prngs 论文中发现了这一点:luscher.web.cern.ch/luscher/ranlux
  • 您使用了哪个标准 C 库?你是如何计算平均值的?显示您的代码。
  • 如果您足够关心随机性来衡量其质量,请不要使用rand()
  • Stack Overflow 不仅适合您。为自己找到一些解决方案对您有好处。但是仍然存在一个问题,无论您使用的rand 似乎都有偏见。这是应该为未来的读者澄清的信息。告诉我们您使用哪个标准 C 库 C。GNU C 库?其他图书馆?你是如何计算平均值的?编辑问题以说明使用的库并包含代码。

标签: c random montecarlo


【解决方案1】:

这取决于您的 C 实现。有些人比其他人具有更高质量的rand 实现。也许使用 arc4random 或其他一些基于加密的 PRNG。

【讨论】:

    【解决方案2】:

    我个人最喜欢的是xoroshiro。它通过了大多数伪随机测试,而且速度非常快,比rand() 快得多。

    【讨论】:

      【解决方案3】:

      当然,在典型情况下,rand() 是出了名的糟糕 PRNG。 (在我的系统上,man rand 打印“rand, rand_r, srand, sranddev -- 随机数生成器错误”。)

      rand 在某些情况下往往很好,但我认为人们普遍认为,它对于体面的蒙特卡罗模拟永远不够好。撇开它的分布不谈,它的周期往往不够长。 (典型的实现保持约 32 位状态,因此它们在 43 亿个样本后开始重复。)

      话虽如此,(double)rand()/RAND_MAX 在我的机器上平均为 0.5 - 准确地说,在 1,000,000,000 个样本后我得到了 0.500004。我怀疑你的系统的实现可能被破坏了——我想到的一种可能性是它错误地发出了从 0 到 RAND_MAX-1 范围内的数字。您可以尝试平均 rand()/(RAND_MAX-1.) 看看会发生什么。

      (ObIdleOpinionating:我希望系统能够更好地实现rand(),而不是告诉你不要使用它并以不同的非标准名称给你一个更好的 PRNG。但我希望什么都没关系,因为实现一个蹩脚的rand() 以及更好但非标准的替代名称版本似乎是每个人都在做的事情。)

      【讨论】:

      • rand 是一个 API,而不是一个伪随机数生成器。如果没有指定具体的实现,说它是一个糟糕的生成器是不正确的。说一些历史上的实现很糟糕可能是正确的。
      • 我认为rand 的主要问题是 C 标准本身没有指定任何特定的质量目标,除了 RAND_MAX 至少 32767。它的字面意思是 “没有保证产生的随机序列的质量,并且已知某些实现会产生具有令人痛苦的非随机低位比特的序列。具有特殊要求的应用程序应使用已知足以满足其需求的生成器" . POSIX 至少没有添加关于最短期限的要求。
      • @EricPostpischil 理论上你是对的,我希望我能同意你的看法。但糟糕实现的普遍率似乎至少为 95%,并且共识建议(如该线程中所反映的那样!)是“不要使用它”。
      猜你喜欢
      • 2019-12-12
      • 2018-09-27
      • 1970-01-01
      • 2015-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-30
      相关资源
      最近更新 更多