c - srand/rand 缓慢变化的起始值

标签 c macos srand

我写了一个简单的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/

相关文章:

c++ - 用于验证事务模块 (.cpp) header 中 #define(d) 整数提供的范围的条件语句

c++ - 在 C++ 中使用 srand() 的测试用例的新值集

c - Linux TCP套接字崩溃

c - 不会停止等待用户输入的游戏循环

git - 无法将 SourceTree 连接到 AWS CodeCommit

macos - FFmpeg 编译错误

c - 随机数游戏C

c - 骰子游戏坚持原始分数但成功循环

c - 我如何避免此链接错误?

c - 以相反的行顺序打印文件的内容