为什么(rand()%中的任何东西)在C++中总是0?

Zac*_*ffe 3 c++ random

我无法让rand()在C++中工作.rand()通常给我一个非常大的数字.当我尝试使用模运算符(%)给它一个范围时,它总是返回0,无论如何.

在程序开头播种随机数生成器也无济于事.

asv*_*kau 8

我认为如果随机生成器算法将某个位模式保留为零,这种情况很常见.(例如,如果低位为零,则某个低常量的数字mod将始终为零.)

也许你应该尝试类似的东西:

const int desired_maximum = /* ... */;

int r = (((double)rand()) / RAND_MAX) * desired_maximum;
Run Code Online (Sandbox Code Playgroud)

例如,在此联机帮助页链接中,它说:

C:Numerical Recipes in C:The Scientific of Scientific Computing(William H. Press,Brian P. Flannery,Saul A. Teukolsky,William T. Vetterling; New York:Cambridge University Press,1992(2nd ed.,p.277)) ,以下评论:

"如果你想生成一个介于1和10之间的随机整数,你应该总是使用高位来实现它,就像在

j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
从来没有任何类似的东西
j = 1 + (rand() % 10);
(使用低阶位)."

  • 请不要盲目推荐高位.这完全取决于使用的PRNG.Numerical Recipes是一本很好的书,但特别是旧版本充满了危险的建议.这是其中一个例子.此外,即使那些使用LCG*的C/C++实现也会丢弃低位.人们从70年代开始学习. (4认同)

Ale*_*lli 7

以下代码对我来说很合适(每次运行时发出一个介于0和0之间的随机数):

#include <cstdlib>
#include <ctime>
#include <iostream>

int main()
{
    std::srand(time(0));
    std::cout<<(std::rand() % 1000)<<std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • @Zachary:您可能想要在编译器上显示警告.这就是你可以让编译器捕获的东西. (8认同)

Jer*_*fin 5

看来您的迫在眉睫的问题已经解决了,但我认为仍然值得一提。使用余数将兰特的输出钳位到指定范围通常会导致结果偏差。具体来说,如果生成器的范围(对于C或C ++,则为RAND_MAX)不是您要限制的范围的倍数,则某些输出将比其他输出更频繁地出现。为了进行比较,请考虑尝试将11个糖果平均分配给3个孩子(不分成任何一个)。唯一的方法就是不要分发一些糖果。同样,对于随机数生成器,在输出中获得均匀分布的唯一方法是不使用某些输入。

int rand_lim(int limit) {
/* return a random number between 0 and limit inclusive.
 */
    int divisor = RAND_MAX/(limit+1);
    int retval;

    do { 
        retval = rand() / divisor;
    } while (retval > limit);

    return retval;
}
Run Code Online (Sandbox Code Playgroud)

正如asveikau在其文章中指出的那样,您通常希望使用典型线性同余生成器中的高位。较低的位通常更可预测。通过除法而不是取余数,可以保留高位。尽管确实有一个while循环,但它通常只执行一次,很少执​​行两次以上,因此对性能的影响很小。

这是否值得取决于您对所生成数字的使用-如果您想要骰子或孩子们将玩几次的游戏纸牌,那么使用余数通常不会有什么坏处。如果您尝试进行某种形式的蒙特卡洛模拟(例如),则可能需要多加注意。