1

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?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Peter Franek
  • 577
  • 3
  • 8
  • 25
  • 1
    It's a function, not a command. – user207421 Jun 18 '17 at 13:55
  • 1
    [`#include `](http://en.cppreference.com/w/cpp/numeric/random) – JVApen Jun 18 '17 at 14:00
  • 3
    Possible duplicate of [Generate random numbers using C++11 random library](https://stackoverflow.com/questions/19665818/generate-random-numbers-using-c11-random-library) – zett42 Jun 18 '17 at 14:03
  • 1
    I get results that seem to have a standard deviation around 1000. Your platform's random number generator must not be very good - use a better one such as mersenne twister from ``. – interjay Jun 18 '17 at 14:05
  • Will be grateful if someone comments on the downvotes.. – Peter Franek Jun 18 '17 at 14:11
  • Dual tagging posts C and C++ tends to attack down votes. Although the code may apply to more than 1 languages, the solution is often language specific. – chux - Reinstate Monica Jun 18 '17 at 14:30
  • @chux Thanks. I'm quite new both here and in programming in general; for the future, would you advise me to tag a question like this in the "c" only? – Peter Franek Jun 18 '17 at 14:31
  • 2
    @PeterFranek: Since the code in the question uses `cout` which is not C, you should tag such questions as C++. You get a radically different (better) answer since C++11 (unless it was C++14) has the superior random facilities and C is lacking anything comparable. – Jonathan Leffler Jun 18 '17 at 14:37
  • The sample code contains `#include` and `std::cout << s;` so tagging C only makes sense with code change. – chux - Reinstate Monica Jun 18 '17 at 14:38

3 Answers3

3

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.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
2

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

0

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.

aardvarkk
  • 14,955
  • 7
  • 67
  • 96
  • Thanks for the bernoulli suggestion.. however, the effect of RAND_MAX being possibly odd has, I think, only very negligible effect in this case. – Peter Franek Jun 18 '17 at 14:02
  • 3
    It's `RAND_MAX+1` that needs to be divisible. And `RAND_MAX+1` will be divisible by two in almost any implementation. Even if it isn't, the imbalance will be extremely small here (At most 0.006% more 0 values than 1 values). – interjay Jun 18 '17 at 14:03
  • @interjay Thanks for the comment. I've edited the answer. – aardvarkk Jun 18 '17 at 14:05