简体   繁体   中英

clang - poor rand() implementation

I had made a Pong game where I had to randomize the throw of the ball. To do this, I used the inbuilt random number generator and got good results in Ubuntu/GCC. On porting the code to Mac and compiling, the ball would only be projected in a single direction, meaning that the rand() function in clang was not working as expected.

I have since reverted to a custom number generator, but here's the original problematic code in the game:

srand(time(NULL));
float ang = ((float)rand())/RAND_MAX * 120 - 60;
int side = (int)(((float)rand())/RAND_MAX * 2);

Upon further inspection, I created the following test program and compiled and ran it on both platforms.

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

int main(int argc, char** argv) {
    while (1) {
        int now = time(NULL);
        printf("Time now is %d\n", now);
        srand(now);
        int random = rand();
        printf("Random number generated is %d\n", random);
        sleep(1);
    }
}

The results (tabulated and calculated against RAND_MAX , which is 2147483647 on both systems) are as follows:

在此处输入图片说明

The results speak for themselves. While there is randomness in the clang version, as compared to the value of RAND_MAX , the randomness is very poor and is evidenced by the standard deviation of 0, compared to the standard deviation of 0.328 on gcc.

What are the reason(s) for this poor behaviour of rand() on clang ? I would also like to see the reference implementation of this function in the header file. This seems nonstandard, and I must not be the only one who ran into problems while porting programs using this method to Mac. What other design principles are good practice while using/relying upon random number generators?

Reason it was Not Behaving Right:

So I don't know the exact implementation for apple's clang implementation for rand, however I know it was done as a LCG, or Linear Congruential Generator. The way it works is basically a formula:

In the formula, would be the RAND_MAX , andare some constant defined by the compiler. Apple's Clang used 16807 and 0 respectably.

The return for rand() is , and last return of rand() or the value you put in srand() would be .

If you just want a sequence of number, that are kinda random, this works pretty well, as it would eventually return all numbers between 0 and RAND_MAX , without a noticeable pattern by human.

However, with some calculations, you can easily spot it would have some problem if you just put a continuous sequence of number in the place ofin that formula (which is what you did). The difference between each call of rand() would be exactly equals to , except when is actually close to RAND_MAX .


Correct Way of Using it:

The correct ways of getting random number through rand() function is only calling srand() once at the beginning, and use only rand() in the loop.

Alternatively, there are many other random generating formula you could look for, and you can probably find some here: How to generate a random int in C?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM