我写了一个简单的BASIC interpreter我在 Clang/macOS 上运行。为了实现 RND(),希望尽可能使用标准 C,我使用了 srand/rand。在程序开始附近(在 Retrobasic.c 中),我使用 null 或用户传递的值调用 srand(是的,一次):
if (random_seed > -1)
srand(random_seed);
else
srand(time(NULL));
只有一个地方产生数字:
result.number = ((double)rand() / (double)RAND_MAX);
调用此函数的代码是INT(RND()*25)+1
,我注意到它每次运行都会返回相同的起始数字,但它大约每小时都会发生变化。所以昨晚总是 25,今天早上是 2,现在是 3。我在 srand
后面放了一个 printf("%d", rand());
>。果然,这让我很感动:
200829549
200964005
201098461
201232917
201703513
这似乎是第三/第四位数字中的伪秒,这解释了我所看到的行为。这添加了 printf 通过泵送序列来“修复”它,然后对 rand 的任何后续调用都可以。我真的很想以正确的方式理解/解决这个问题。
Clang 提示 srand(time(NULL))
,说它需要一个 unsigned int
并希望我将 time_t
转换为使警告静音。 time_t
取决于实现,但我怀疑它确实是一个unsigned long
?也许这是 32/64 位转换进入 srand 时出现的问题?我发现了一些诱人的帖子,like this one ,但没有最终结论。
这不是关于糟糕的随机序列,序列很好(满足我的需要)。有一些线程是关于错误的起始数字,但它们最终总是 improper srand
use 。有人有建议吗?
最佳答案
time_t
可以是浮点类型,这可以解释为什么种子只是偶尔改变。如果 time_t
自某个起始时间点(其中分数描述了一天中的时间)以来保持 天,那么您每天只会看到一次新种子。
您可以尝试使用timespec_get
(至少需要 C11)。 struct timespec
的纳秒部分被指定为 long
,因此转换为 unsigned
可以正常工作:
#include <stdlib.h>
#include <time.h>
void seeder() {
struct timespec ts;
timespec_get(&ts, TIME_UTC);
srand((unsigned ) ts.tv_nsec);
}
int main(void) {
seeder();
// ...
}
关于c - srand/rand 缓慢变化的起始值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76367489/