Peter Franek
Peter Franek

Reputation: 697

Alternatives to using rand() function in C++

I tried this simple code, which "randomly" generates 1's or -1's million times and sums them up:

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

int pos_or_neg()
{
    if (rand()%2==1) return 1;
    else return -1;
}

int main()
{
    int i,s=0;
    srand (time(NULL));
    for (i=0;i<1000000;i++)
        s+=pos_or_neg();
    std::cout << s;
}

If the rand() instances were independent, then the result should be normally distributed with standard deviation 1000, but I'm getting results of magnitude hundreds at most. If I generate more numbers --- such as 100 millions --- then this is even more striking and the magnitude even decreases!

Is rand() really that bad or am I doing something wrong? In the first case, what are some good alternatives?

Upvotes: 1

Views: 5204

Answers (3)

Francisco Geiman
Francisco Geiman

Reputation: 400

Using the following code I have obtained a standard deviation around 1000.

#include <random>
#include <iostream>

constexpr int N = 1000000;

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, 1);

    int frequencyOfOnes = 0;
    for (int n=0; n<N; ++n)
        frequencyOfOnes += dis(gen);
    std::cout << "Out of " << N << " events, " << frequencyOfOnes << " had 1 as a result " << std::endl;
}

As pointed out by @zett42, there is already a question about this topic. You can go there for more information about that topic.

Generate random numbers using C++11 random library

You should definitely check out this talk, so as to understand why using rand with modulo might not be a good idea.

https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

So if you want an uniform distribution, I strongly suggest that you use http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution

Upvotes: 2

Pete Becker
Pete Becker

Reputation: 76245

rand() is usually implemented with a linear congruential generator, and linear congruential generators are notoriously non-random in their low bits. So either use a different generator, or pick out some other bit; for example, rand() & 0x10.

Upvotes: 3

aardvarkk
aardvarkk

Reputation: 15996

One thing to consider is that taking rand() and using mod on it assumes that RAND_MAX+1 is evenly divisible by your mod function. If it's not, you'll have at least an imbalance because you won't choose "even" the same number of times you'll choose "odd".

In your case of just trying to provide a "coin flip" of random values, use bernoulli_distribution instead.

Upvotes: 0

Related Questions