【问题标题】:Strange behaviour with rand()rand() 的奇怪行为
【发布时间】:2010-12-29 17:06:33
【问题描述】:

为什么条件 rand() % 3 大约每 3 次为真? rand 真的很随机​​,不是吗?

【问题讨论】:

  • 请向我们展示您的代码。
  • 大约 2/3 的时间应该是真的。
  • rand() 不是随机的,是pseudo random,不是一回事。
  • @Darin,伪随机性与这种测试无关。结果数字是均匀分布的,因此如果做得好,测试将导致 66% 的成功。

标签: c random


【解决方案1】:

当然,您意识到即使是一枚公平的硬币也可以连续给您十个正面。有一个概率可以分配给该组合。

一枚公平的硬币在许多次试验中会出现半正面和半反面,但不能保证在短期内达到 50/50。

你自己对物理世界的经验告诉你你的结论是错误的。 rand() 也是如此。

【讨论】:

  • 然而,rand() 的许多实现确实显示出较差的随机性,尤其是当您查看低位时。如果 RNG 陷入循环,即使分发正常,这也是一个问题。如果你有一次抛硬币的过程是 HTHTHTHTHTHTHTHTHT……很长一段时间,即使分布完全符合预期,你也会怀疑出了什么问题。如果 RNG 陷入循环,也可能导致分布(永远)偏斜。
  • DieHard 测试应该足以证明随机数生成器是否足够。不知道这个实现有没有受到过。
【解决方案2】:

正如 Linux manpage for rand() 所说:

但是,在较旧的 rand() 实现中,以及在不同系统上的当前实现中,低阶位的随机性远低于高阶位。当需要良好的随机性时,请勿在旨在可移植的应用程序中使用此功能。

因此您可能想要使用不同的随机数生成器,或者提取更高阶的位(这可能表现出更多的随机性)。

rand() 的典型实现是linear congruential generator,它只不过是一些具有特殊属性(相对素数)的数字的乘法和加法。例如,几个实现:

  • MSVC 2010 rand():

     return( ((ptd->_holdrand = ptd->_holdrand * 214013L
                + 2531011L) >> 16) & 0x7fff );
    
  • 来自 IAR 工作台的rand()

     (x) * 1664525L + 1013904223L           
    

您会注意到 MSVC 2010 的 rand() 将结果向右移动,我认为这有助于解决 Linux 手册页中描述的关于低位非随机性的问题。

但是,如果您想提高结果的随机性,您可能需要考虑使用基于 Mersenne twister 之类的例程,该例程的实现在 Internet 上很容易获得。

【讨论】:

  • 我不太精通统计分析或线性同余算法的分析,但如果低位不是很随机,它很可能会导致 33% 的偏差。请注意,引用没有详细讨论低位的行为 - 只是它们不是很随机。
  • LCG 远非完美(不过,当您考虑数字向量时,真正的缺陷开始显现,从技术上讲,d 元组在以 d 维绘制时显示出规则的晶格结构),实际上较低的位是不是那么随机(非常小的周期),而是模3运算的结果是AFAIK在低位上不是本地的(与例如模2相反)。 33% 似乎太高了。我希望我现在有一个带有 gcc 的盒子,因为我很好奇 :) 不幸的是我在 hols...
  • @Dr. G:显然你比我更擅长这个。那条评论有一半不在我的词汇表中! (d 元组?d 维?晶格结构?)
【解决方案3】:

这段代码我也遇到了同样的问题:

#include<iostream.h>
#include<stdlib.h>
int main()
{
    srand(NULL);       
    cout << rand() % 10 + 1;
}

运行 10 次后,我每次都得到 1。但是我把种子改成这样:

#include<iostream.h>
#include<stdlib.h>
//new include:
#include<time.h>
int main()
{
    srand(time(NULL));       
    cout << rand() % 10 + 1;
}

这是因为 RANDOMIZER 采用种子(srand()),它恰好在第一个中为空,然后运行给定算法,输出为 1。如果按时间确定种子,则生成一个“随机”的结果。 希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多