【问题标题】:Generating a random bit - lack of randomness in C rand()生成随机位 - C rand() 中缺乏随机性
【发布时间】:2012-07-10 16:51:34
【问题描述】:

我正在使用rand() 生成 0 或 1 (rand() % 2)。我正在使用当前时间播种 (srand(time(NULL)))。

经过多次调试,我意识到rand() 永远不会连续 16 次或更多次返回偶数(奇数)数。

这是一个已知问题吗?有没有 C 自带的更好的 PRNG?

我正在使用 Visual Studio 2010 在 Windows 7 上运行。

【问题讨论】:

  • rand never returns an even (odd) number 16 or more times in a row - 嗯...你测试了多少次?少于2^16 次?
  • 连续获得16个赔率的概率为(1/2)^16。这是相当低的......
  • 大约十亿次,足以让 16 个偶数(奇数)大致出现 128 次(如果我的计算正确的话)。
  • rand 的一些(旧)实现中,低位位的随机性低于高位位。试试(rand()>RAND_MAX/2?1:0)
  • 模数偏差可能是个问题。见stackoverflow.com/a/10984975/562769

标签: c random


【解决方案1】:

不要使用rand()%2,而是尝试rand()>(RAND_MAX/2)。您只能假设 rand() 在区间 [0, RAND_MAX] 上是一致的。

编辑:这是 Shahbaz 在 cmets 中提出的,我是在发布此答案后才注意到的。

编辑: ArjunShankar 在我之前的措辞中叫我出来:“rand() 仅在区间 [0, RAND_MAX] 上被指定为统一的”

来自 C99 标准:

rand 函数计算范围为 0 到 0 的伪随机整数序列 RAND_MAX。

从技术上讲,没有指定均匀性(或等分布),但它是用于实现常用 PRNG(例如 Mersenne Twister)的事实上的标准。这是为了允许程序员轻松创建具有非均匀分布的自定义 PRNG。如果没有这个属性,程序员就不得不从头开始实现自定义 PRNG。

【讨论】:

  • "rand() 仅在区间 [0, RAND_MAX] 上被指定为统一的——Microsoft documentation for rand 没有说明统一性。还有其他来源吗?
  • 好的,我也检查了 C99。不保证范围内的一致性。当然,这并不意味着您的解决方案不正确。这很可能实际上确实实现了 OP 正在测试的那种序列。
  • 简洁的答案。 +1,因为我想让 OP 尝试一下。也因为rand 很便宜。
【解决方案2】:

我建议使用更好的 RNG。您在 Windows 上运行,因此您可以使用 rand_s:这是一个使用 Windows 加密 RNG 的 Microsoft 扩展。

【讨论】:

  • 加密RNG 并且对于大多数应用程序来说确实过大了。它是加密的(与 pRNG 相比确实非常慢),因为这些位实际上是随机的,来自外部事件,而不是伪随机。这也使得调试变得更加困难。
  • @sfstewman 我建议权衡是由问题的作者评估和决定。
  • 您的答案虽然可以解决 OP 的问题,但也会产生新的问题。加密 RNG 并不真正适合一次生成数十亿个随机位。这将因 OP 代码的模 2 丢弃所有对 rand_s 的调用中的一位以外的所有位而更加复杂。那是 31 或 63 位的纯熵消失了。您至少应该警告 OP 并建议他们可以使用 rand_s 中的每一位,而不仅仅是 LSB。
【解决方案3】:

rand() 是众所周知的烂。 random() 好一点(有时),但drand48() 及其家族要好得多。

如果您需要比这更好的方法,请查看 mersene twister 或其他 PRNG 库。或者查看 /dev/random 是否可以提供足够的数据来满足您的需求。

【讨论】:

  • 谷歌搜索表明不是。 Windows 上还有其他可用的随机数生成函数,例如 CryptGenRandom,或者您可以使用外部库,例如 MT - math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
  • rand() 历来有问题。有关数学,请参阅 George Marsaglia 的 famous article。你的 C 库可能有也可能没有这个问题。对于任何需要严重随机性的东西,Mersenne Twister(链接由@evilotto 提供)或其他现代 pRNG 是最好的。
【解决方案4】:

嗯,您可以使用 Mersenne Twister 或 WELL 的算法。 WELL 的代码在这里(我没有足够的声誉) http://i.stack.imgur.com/q6VPL.png

【讨论】:

    猜你喜欢
    • 2014-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 2018-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多