3

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:

enter image description here

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?

Aniruddha Deb
  • 272
  • 2
  • 7
  • 1
    According to Mac themselves, their implementation of `rand()` is bad: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/srand.3.html ... and obsoleted by `random()` – pmg Oct 31 '20 at 08:32
  • 1
    I'd love to see the source code of this srand() and rand() implementation. – President James K. Polk Oct 31 '20 at 14:36
  • 1
    I'd say the most important principle is to choose a random number generator that has stood up to analysis and is still respected today. The only thing that `rand()` has going for it is portability. Note that there is no requirement that `rand()` be poorly implemented, it just seems that it often is. – President James K. Polk Oct 31 '20 at 14:49
  • 1
    What happens if you call `rand()` multiple times after calling `srand()`? Does it still vary only slightly? – the busybee Oct 31 '20 at 19:44
  • Don't blame clang or praise gcc; the random number generator is part of the system standard library, not the compiler. Rather, it's MacOS vs glibc. – Nate Eldredge Nov 08 '20 at 04:48
  • [srand() — why call it only once?](https://stackoverflow.com/q/7343833/995714) – phuclv Nov 08 '20 at 15:23

1 Answers1

2

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,  and  are 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 of  in 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?

Ranoiaetep
  • 5,872
  • 1
  • 14
  • 39
  • 1
    this is the result of the trashy `rand()`: [Why does rand() % 7 always return 0?](https://stackoverflow.com/q/7866754/995714), [Rand() % 14 only generates the values 6 or 13](https://stackoverflow.com/q/20263187/995714) – phuclv Nov 11 '20 at 02:16