srand(1) 和 srand(0) 有什么区别

发布于 2024-12-14 12:28:28 字数 1005 浏览 0 评论 0原文

我刚刚发现 srand(1) 将 C(++) 的 PRNG 重置为调用 srand 之前的状态(如 参考)。 然而,种子 0 似乎做了同样的事情,或者在调用 srand 之前的状态似乎使用了种子 0。 这两个调用有什么区别,或者它们做同样事情的原因是什么?

例如此代码(在 Ideone 上执行

#include <stdio.h>
#include <stdlib.h>

int main() {
    for (int seed = 0; seed < 4; seed++ ) {
        printf( "Seed %d:", seed);
        srand( seed );
        for(int i = 0; i < 5; i++ )
            printf( "    %10d", rand() );
        printf( "\n");
    }
    return 0;
}

返回

Seed 0:    1804289383     846930886    1681692777    1714636915    1957747793
Seed 1:    1804289383     846930886    1681692777    1714636915    1957747793
Seed 2:    1505335290    1738766719     190686788     260874575     747983061
Seed 3:    1205554746     483147985     844158168     953350440     612121425

I just found out the hard way that srand(1) resets the PRNG of C(++) to the state before any call to srand (as defined in the reference).
However, the seed 0 seems to do the same, or the state before any call to srand seems to use the seed 0.
What’s the difference between those two calls or what is the reason they do the same thing?

For example this code (execute on Ideone)

#include <stdio.h>
#include <stdlib.h>

int main() {
    for (int seed = 0; seed < 4; seed++ ) {
        printf( "Seed %d:", seed);
        srand( seed );
        for(int i = 0; i < 5; i++ )
            printf( "    %10d", rand() );
        printf( "\n");
    }
    return 0;
}

returns

Seed 0:    1804289383     846930886    1681692777    1714636915    1957747793
Seed 1:    1804289383     846930886    1681692777    1714636915    1957747793
Seed 2:    1505335290    1738766719     190686788     260874575     747983061
Seed 3:    1205554746     483147985     844158168     953350440     612121425

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

诠释孤独 2024-12-21 12:28:28

glibc 是如何做到的:

围绕行181 的glibc/stdlib/random_r.c,内部函数__srandom_r

 /* 我们必须确保种子不为 0。在这种情况下可以任意取 1。 */
  如果(种子== 0)
    种子=1;

但这就是 glibc 的做法。这取决于C标准库的实现。

How glibc does it:

around line 181 of glibc/stdlib/random_r.c, inside function __srandom_r

  /* We must make sure the seed is not 0.  Take arbitrarily 1 in this case.  */
  if (seed == 0)
    seed = 1;

But that's just how glibc does it. It depends on the implementation of the C standard library.

瑶笙 2024-12-21 12:28:28

这可能是一个实现细节。该标准要求随机种子 1 是特殊的,并且特定随机生成器算法的内部寄存器可能是零初始化的,从而导致种子(0)和种子(1)具有相同的随机序列。我什至打赌你的 srand() 实现的第一行看起来像:

if ( seed == 1 ) seed = 0;

强制符合标准的行为。

一般来说,rand()和srand()的随机数生成器不需要为不同的种子提供不同的序列,而是为相同的种子提供相同的序列。所以,不要依赖不同的种子生成不同的随机序列,你应该没问题。如果没有,欢迎来到特定于实现的乐趣。

It is probably an implementation detail. The standard mandates that the random seed 1 is special, and the internal register of your specific random generator algorithm is probably zero-initialized, thus causing the same random sequence for seed(0) and seed(1). I'd even wager that the first line of your srand() implementation looks like:

if ( seed == 1 ) seed = 0;

to force standard-conformant behaviour.

Generally, the random number generators for rand() and srand() are not required to give different sequences for different seeds, but the same sequence for the same seed. So, don't rely on different seeds generating different random sequences, and you should be fine. If not, welcome to implementation-specific fun.

葵雨 2024-12-21 12:28:28

C 和 C++ 标准都没有详细说明 rand()srand() 的实现细节。细节几乎完全由实施者决定。 C 标准要求:

如果随后使用相同的种子值调用 srand,则应重复伪随机数序列。如果在对 srand 进行任何调用之前调用 rand,则应生成与首次使用种子值 1 调用 srand 时相同的序列。

但它不包含任何不同种子必须的要求产生不同序列。显然,在您的系统上,零和一的种子具有相同的效果。我猜想这是为了提供与某些软件的向后兼容性,这些软件期望 srand(0) 将 PRNG 重置为其初始状态。

Neither the C nor the C++ standards say much about the specifics of the implementation of rand() and srand(). The details are left almost entirely up to the implementor. The C standard requires that:

If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.

but it does not contain any requirement that different seeds must produce different sequences. Apparently, on your system, seeds of zero and one have the same effect. I would guess that this is to provide backwards compatibility with some piece of software that expects srand(0) to reset the PRNG to its initial state.

不寐倦长更 2024-12-21 12:28:28

如果种子设置为 1,则生成器将重新初始化为其初始值,并生成与调用 rand 或 srand 之前相同的值。 cplusplus.com/reference/clibrary/cstdlib/srand/" rel="nofollow">srand 参考

If seed is set to 1, the generator is reinitialized to its initial value and produces the same values as before any call to rand or srand. Taken from the srand reference

夜雨飘雪 2024-12-21 12:28:28

在阅读手册页时,他们都指出“如果未提供种子值,则 rand() 函数将自动使用值 1 进行种子设定”。这可能就是您链接到的参考页面指出使用 1 进行播种会重置状态的原因。

使用 0 和 1 进行播种时会发生相同的结果,这很可能取决于实现,并且不应指望在所有平台上都会发生。

When reading manual pages, they all state that "If no seed value is provided, the rand() function is automatically seeded with a value of 1." This is probably why the reference page you link to states that seeding with 1 resets the state.

That the same result happens for seeding with both 0 and 1 is most likely implementation dependant, and should not be counted on happening on all platforms.

凶凌 2024-12-21 12:28:28

srand() 函数使用该参数作为后续调用 rand() 返回的新伪随机数序列的种子。如果随后使用相同的种子值调用 srand(),则应重复伪随机数序列。如果在对 srand() 进行任何调用之前调用 rand(),则应生成与首次使用种子值 1 调用 srand() 时相同的序列。

也许有用: http://pubs.opengroup.org/onlinepubs/009695399/functions/rand.html

The srand() function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand(). If srand() is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand() is called before any calls to srand() are made, the same sequence shall be generated as when srand() is first called with a seed value of 1.

Maybe useful: http://pubs.opengroup.org/onlinepubs/009695399/functions/rand.html

奢欲 2024-12-21 12:28:28

指定 1 的原因是因为如果种子设置为零,一些随机数生成器将卡在零处。例如移位寄存器和乘法同余类型,即 r(n+1) = (A * r(n))mod M。

许多 C 实现使用线性同余 r(n+1) = (A * r(n) + B) mod M,B 0 不会被卡住。

The reason 1 is specified is because some random number generators will get stuck at zero if the seed is set to zero. For example shift-registers and Multiplicative congruential types i.e. r(n+1) = (A * r(n))mod M.

Many C implementations use Linear Congruential r(n+1) = (A * r(n) + B) mod M, B <> 0 which don't get stuck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文