rand()每次给出几乎相同的数字

问题描述 投票:0回答:5

我正在学习C,我想生成一个0到6400之间的数字。这是我想出的代码:

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

int main()
{
    srand(time(0));
    int i = (rand() % 6401);
    printf("Random number between 0 and 6400: %d\n", i);
    return 0;
}

当我从命令行编译并运行此代码时,我得到一些非常奇怪的结果:

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6282

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6282

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6285

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6285

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6289

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6289

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6292

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6292

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6295

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6298

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6298

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6302

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6302

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6305

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6305

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6308

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6308

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6311

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6311

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6315

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6315

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6318

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6318

K:\C\Labo\Oefeningen 2019>a
Random number between 0 and 6400: 6321

K:\C\Labo\Oefeningen 2019>

数字都不同,但是我希望0和6400之间的分布比较均匀。奇怪的是,我在一小时前使用相同的函数没有问题吗? (我以前曾用它来生成较小的数字。)我敢肯定,这确实是我很想念的东西,但是我已经呆了一个小时了。

编辑:我知道当您在同一秒内运行代码时,它将提供相同的值。我在两次执行之间等待了几秒钟(10-20),仍然得到相同的结果吗?这些值很少相同,只是在100%的时间内非常非常相似。我该如何解决?

c random srand
5个回答
3
投票

time()的分辨率为1秒。因此,您的程序平均只有经过半秒后才会生成不同的值。

如果编译器支持C11,则可以使用更高分辨率的函数timespec_get()。然后,您的srand(time(0));将转换为以下内容:

struct timespec ts;
timespec_get(&ts, TIME_UTC);
srand(ts.tv_nsec);

这里ts.tv_nsec是时间戳的纳秒部分,其分辨率应足以满足您的目的。

[如果您的编译器不支持C11,您仍然可以使用比time()更好的随机种子源,分辨率约为1毫秒(实际分辨率由CLOCKS_PER_SEC宏给出):clock()函数。然后您的种子代码将是

srand(clock());

尽管请注意,它实际上可能是不良的熵源,尤其是在您的操作系统不忙的情况下,因此程序将以可预测的速度运行。这是因为clock()时代的开始与程序的执行有关,而与实时无关。例如可能会更好使用clock()time(0)的总和获得更多不可预测的值:

srand(time(0)+clock());

0
投票

计算机并不会真正生成随机数。因此,当您在同一秒执行两次代码时,它将返回相同的值。为了获得更好的结果,您可以在srand中添加getpid()的值。

请记住,这仍然不是真正的随机。


0
投票

如果您的rand被破坏,则可以尝试使用xorshift伪随机值之一数字生成器。它们不是完美的,但是实现的时间很短。足以供您自己使用。

这里是一个实现示例:我将此one用作参考。

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

uint64_t    xorshift64s(uint64_t seed)
{
    static uint64_t i = 1;

    if (seed != 0)
        i = seed;
    i ^= i >> 12;
    i ^= i << 25;
    i ^= i >> 27;
    i *= 0x2545f4914f6cdd1d;
    return (i >> 32);
}


int main()
{
    srand(time(0));
    int i = (rand() % 6401);
    printf("rand    : Random number between 0 and 6400: %d\n", i);
    xorshift64s(time(0));
    int j = (xorshift64s(0) % 6401);
    printf("xorshift: Random number between 0 and 6400: %d\n", j);
    return 0;
}

0
投票

[如果其他人遇到此问题,我想我找到了一种解决方法。我知道这不是一个完美的解决方案,但这是唯一对我有用的解决方案。我认为编译器中使用的随机数生成器根本不喜欢类似的种子。使用此代码段,它实际上会生成一些可接受的半随机数:

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

int main()
{
    srand((unsigned int)time(0) * 100000000);
    int i = (rand() % 6401);
    printf("Random number between 0 and 6400: %d\n", i);
    return 0;
}

这是我从btw获得垃圾桶编译器的位置:http://tdm-gcc.tdragon.net/download


0
投票

rand生成的数字并不是真正随机的,它们是通过公式生成的。这就是为什么播种既可能又必要的原因。根据所使用的公式,种子和前几个随机数之间可能具有高度相关性。

治愈方法是使用更好的公式(不是rand),使用更多的随机种子,或在播种后立即浪费一些随机数。

© www.soinside.com 2019 - 2024. All rights reserved.