5

这可能是一个愚蠢的问题,但我真的很纠结这个概念。我正在阅读一个解释数组和 rand() 函数的教程。我有两个问题。

第一个是,显然要模拟一个骰子,我们需要从 1-6 随机生成一个数字。这本书暗示了这一点:

int       RollOne( void ) {
    return (rand() % 6) + 1;
}

对,rand() 可以生成 0-32767 之间的任何数字。然后我们找到这个数除以 6 的余数,然后加 1。例如 3245 是随机生成的。我们将它除以 6,得到 540.8333 并取余数。8.333(我相信截断为 8)然后加 1。除非我要发疯,否则就是 9,它不在 1-6 之间。该程序运行良好,但是我无法理解我们如何使用该代码从 1-6 获得一个数字!任何帮助将不胜感激。

我遇到的第二个问题并不那么重要,但很重要。这本书省略了这段代码的含义:

srand( clock() );

所有提到的是 srand() 使用由 clock() 提供的种子初始化一个随机数生成器。对了,现在我们真的可以在clock()中输入任何东西吗,如果可以的话,它的作用是什么?只需稍微解释一下 srand(clock()) 的作用就可以了。

抱歉发了这么长的帖子,我希望你不介意墙上的文字。任何帮助将非常感激。

谢谢,迈克

回答 谢谢大家:我知道我在做什么。如你们所示, % 运算符不除,它只是找到最高倍数与操作数之间的差异。知道了!我的印象是余数意味着小数。即如果 7/2 = 3.5,则余数为 0.5。现在我写出来了,我知道我有多愚蠢。很高兴我的 A-level 数学很重要.....
再次感谢!

4

6 回答 6

8

你的例子有点不正确:

如果您随机生成 3245,将其除以 6 得到 540.8333(因为整数数学,您实际上得到 540)。余数为 3245 - 6 * 540,即 5。5+1 为 6:D

于 2012-08-02T13:56:01.957 回答
4

3245 是随机生成的。我们将它除以 6,得到 540.8333 并取余数。

您对整数截断和余数感到困惑。当您使用整数数学将 3245 除以 6 时,余数为 5(或 0.83333 * 6 = 5)。

另一种查看方式是 540 * 6 = 3240,余数为 5。

于 2012-08-02T14:01:52.093 回答
4

rand(clock()) 如何工作

种子只是一个开始工作的数字。

计算机中实际上没有随机之类的东西(只是随机性的错觉),一切都是涉及种子的复杂计算/转换,在这种情况下,您只需要一个来自系统时钟的数字(种子)开始因为它总是在变化,并且应该总是提供类似随机的结果。

您可能可以将任何您想要的值放在系统时钟值所在的位置。只是不要指望会发生好的随机性。

同样,通常使用clock(),因为它是一个不断变化的值。

想想看,你不应该两次从系统时钟中获得相同的值。总有一些时间流逝,差异可能是一毫秒或更短,但即使变化可能很小,但它与一纳秒前的时间不同。

于 2012-08-02T13:56:59.147 回答
1

对于您的第二个问题, srand 用于播种随机数生成器。如果没有一些专门的硬件,计算机无法真正生成真正的随机数,所以我们要做的是使用数学函数,如线性同余生成器(许多 C 标准库用作默认算法)或Mersenne Twister这会产生一系列高度不可预测的数字,因此必须为这个数学函数播种以赋予它第一个“随机”值。一个好的种子值对于程序的每次运行都会有所不同,只要您不在同一秒内两次运行相同的程序,时间就会很好。你需要种子的原因是因为伪随机数函数不是真正随机的,如果你给函数相同的种子,函数每次都会返回完全相同的数字序列(这对于某些类型的模拟很有用,但大多数时候你希望每次运行都不同)。

锻炼:

运行这个程序:

#include <stdio.h>
int main() {
    srand(1234);
    for (int i=0; i < 20; i++) 
        printf("%d ", rand());
    printf("\n");
}

几次观察会发生什么,然后用 time(NULL) 替换 1234 并观察会发生什么。编写一个 shell 脚本,让修改后的程序非常快速地运行几次,然后观察会发生什么。

于 2012-08-02T15:32:04.100 回答
0

百分比不除。它给出了余数(“mod”函数)。

于 2012-08-02T13:58:06.023 回答
0

余数怎么可能是8?当然,这意味着 6 会再加入一次吗?% 也不是除法函数,它是不同的 div 函数。

于 2012-08-02T13:57:14.630 回答