rand() gives almost the same number every time

不打扰是莪最后的温柔 提交于 2021-02-11 14:55:58

问题


I'm learning C and I want to generate a number between 0 and 6400. This is the code I came up with:

#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;
}

When I compile and run this code from the command line I get some very weird results:

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>

The numbers are all different but I would expect a somewhat even distribution between 0 and 6400. The weird thing is that I was using the same function without problems an hour ago? (I was using it to generate smaller numbers before.) I'm certain it's something really stupid that I'm missing but I've been stuck for an hour now.

EDIT: I know It will give the same value when you run the code within the same second. I waited multiple seconds (10-20) between executions and I still get the same result? The values are rarely the same, they are just very very very similar 100 % of the time. How do I get around this?


回答1:


The numbers generated by rand aren't truly random, they're generated with a formula. That's why seeding is both possible and necessary. Depending on the formula used, there can be a high correlation between the seed and the first few random numbers.

The cures are to use a better formula (something not rand), use a more random seed, or waste a few random numbers just after seeding.




回答2:


time() has resolution of 1 second. So your program will generate at different value only after half a second has passed on average.

If your compiler supports C11, you can use a higher-resolution function, timespec_get(). Your srand(time(0)); will then transform to the following:

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

Here ts.tv_nsec is the nanosecond part of the time stamp, whose resolution should be good enough for your purpose.

If your compiler doesn't support C11, you can still have a better source of random seed than time(), with about a millisecond resolution (actual resolution is given by CLOCKS_PER_SEC macro): the clock() function. Then your seeding code will be

srand(clock());

Note though that it may actually be a bad source of entropy, especially if your OS is not busy, so that the program would run at somewhat predictable pace. It's because beginning of the clock()'s era is related to the program's execution, not to real time. It might be better to e.g. use a sum of clock() and time(0) to get more unpredictable value:

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



回答3:


Computers doesn't really generate random numbers. Thus, when you execute your code twice on the same second it returns the same value. In order to have better result you could add the value of getpid() in srand.

Keep in mind that this still not real random.




回答4:


If your rand is busted, you can try one of the xorshift pseudo-random number generators. They are not perfect but the resulting implementation is very short. It could be enough for your own use.

Here is an implementation example: I used this one as reference.

#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;
}



回答5:


If anyone else runs into this problem I think I found a workaround. I know this isn't a perfect solution but it's the only one that worked for me. I think the random number generator used in my compiler doesn't like similar seeds at all. With this code snippet it actually generates somewhat acceptable semi-random numbers:

#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;
}

This is where I got my garbage can compiler from btw: http://tdm-gcc.tdragon.net/download



来源:https://stackoverflow.com/questions/58150771/rand-gives-almost-the-same-number-every-time

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!