Why does the c function srand() behave differently on Windows vs. Linux, where consecutive seeds produce the first consecutive random number?

huangapple go评论71阅读模式
英文:

Why does the c function srand() behave differently on Windows vs. Linux, where consecutive seeds produce the first consecutive random number?

问题

Here is the translated text:

"这里有一段C代码,进入了一个死循环,每次读取当前时间戳并重置随机种子,然后打印一个随机数并休眠一秒钟。种子是连续的,Windows会为连续的种子生成连续的第一个随机数,而在Linux中并非如此。

许多用C编写的没有自己实现随机数生成器的语言也会出现这个问题,例如lua 5.1"

Please note that code portions are not translated.

英文:

Here we have a piece of c code that goes into a dead loop, reading the current timestamp and resetting the random seed each time, after which it prints a random number and sleeps for one second. The seeds are consecutive, and Windows generates the first random number consecutively for consecutive seeds, which is not the case with Linux.

Many languages written in c that don't have their own implementation of a random number generator also have this problem, e.g. lua 5.1

#include<time.h>
#include<stdlib.h>
#include<stdio.h>
#ifdef __linux__
#include <unistd.h>
#else
#include <windows.h>
#endif

void printRandoms(int lower, int upper,
                            int count)
{
    int i;
    for (i = 0; i < count; i++) {
        int num = (rand() %
        (upper - lower + 1)) + lower;
        printf("%d\n", num);
    }
}

int main(){
    while(1){
        srand(time(NULL));
        printRandoms(1,10000,1);
        #ifdef __linux__
        sleep(1);
        #else
        Sleep(1000);
        #endif
    }
    return 0;
}

The output:

On Windows:
I tried both gcc and clang.
1. gcc.exe (MinGW-W64 x86_64-ucrt-posix-seh, built by Brecht Sanders) 13.1.0
2. (built by Brecht Sanders) clang version 16.0.5
3. gcc.exe (MinGW-W64 x86_64-msvcrt-posix-seh, built by Brecht Sanders) 9.5.0
5237
5238
5239
5240
5241
5242
5243
5245
5246
5247
5248

On Linux:
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
5142
3660
7270
896
9500
3041
6659
5194
8809
7361
5960

I know that's usually the wrong way to use srand(), but was just curious what led to the difference.

答案1

得分: 4

你似乎认为time(NULL)是一个强大的种子,但实际上并不是。尽管Linux版本看起来更随机,但实际上并不是。它和Windows版本一样可预测。这是因为往往可以猜测到种子的时间。而且知道这一点就可以得到数字流,两个版本都一样。(即使你不知道确切的时间,你只有几种可能的流。)srand应该被给予尽可能随机的值。


Windows版本似乎会返回种子作为其第一个值。毕竟,你应该为srand提供一个随机值。而Linux版本则跳过返回种子,从种子后面的值开始。因此,你可以在调用srand后调用rand来复制Linux rand的行为。

srand(time(NULL));
(void)rand();
printRandoms(1,10000,1);

这将使Windows代码看起来与Linux版本一样不可预测。


请注意,连续多次使用随机种子调用srand没有意义。

请注意,在需要随机性重要的地方(例如加密)不应该使用rand。应该使用适当的随机性来源。

英文:

You seem to think time( NULL ) is a strong seed, but it's not. While the Linux version looks more random, it's not. It's just as predictable as the Windows version. That's because it's often possible to guess them time of seeding. And knowing that gives the stream of numbers, in both versions. (Even if you don't know the exact time, you just have a few possibilities of streams.) srand should be given a value as random as possible.


The Windows version appears to return the seed as its first value. After all, you should have provided a random value to srand. The Linux one skips returning the seed and starts with the value that follows the seed. As such, you can replicate the behaviour of the Linux rand by calling rand after calling srand.

srand(time(NULL));
(void)rand();
printRandoms(1,10000,1);

This will make the Windows code look just as unpredictable as the Linux version looks.


Note that it doesn't make sense to call srand with a random seed multiple times in a row.

Note that rand should not be used anywhere where randomness is important (e.g. crpytography). Use a proper source of randomness for that.

答案2

得分: 2

C的rand(),srand(),RAND_MAX并未被规定为非常适合随机数生成,因此一些编译器选择了一个非常弱的和简单的实现。我怀疑这是为了保持兼容性,同时鼓励更好的替代方案。

MinGW-W64 x86_64 似乎是这种情况。


历史上存在非常弱的实现。为了使您的代码具备可移植性和鲁棒性,到2023年为止,没有标准的C库解决方案。需要研究一个能够满足您需求的随机数库。

英文:

As C's rand(), srand(), RAND_MAX are not specified to be very good for random number generation, some compilers choose a very weak and simple implementation. I suspect it is in order to be compliant yet encourage better alternatives.

MinGW-W64 x86_64 appears to be that way.


Historically there have been very weak implementations. To make your code portable and robust, there is no standard C library solution in 2023. One needs to research for a random number library that meets your goals.

huangapple
  • 本文由 发表于 2023年7月13日 13:19:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76676149.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定