0

I'm playing around with rand() and srand() functions and I was trying to make a counter for how many 1's I could get in a row with a 50/50 generator, yet it seems that it caps out at 15 numbers in a row.

#include <cstdlib>
#include <ctime>

using namespace std;

int main() {

    int MostInARow = 0, CurrentInARow;
    bool randomised;
    srand((int)time(NULL));
    for (long int i = 0; i < 100000000; i++) {
        CurrentInARow = 0;
        randomised = rand() % 2;
        while (randomised) {
            randomised = rand() % 2;
            CurrentInARow++;
        }

        if (CurrentInARow > MostInARow) {
            system("CLS");
            MostInARow = CurrentInARow;
            cout << MostInARow;
        }
    }

    return 0;
}

I'd love to learn why this happens.

  • Dunno what you mean. I get different results on every run. Most I got were 26 in a row... But keep in mind that you are dealing with a Pseudo-RNG. If you want a better RNG you need something that takes entropy into account, eg. OpenSSL – Nidhoegger Jun 22 '21 at 08:16
  • 1
    Side note: You (usually) don't get good random distributions by modulo calculations. Better: `value = rand() > RAND_MAX/2`. – Aconcagua Jun 22 '21 at 08:17
  • Because the probability of 15 ones in a row is 0.5^15 = 0.00003052, that is pretty rare – Alexey S. Larionov Jun 22 '21 at 08:17
  • @AlexeyLarionov there's 100,000,000 attempts, you'd expect something like a 24 streak – Caleth Jun 22 '21 at 08:19
  • I tried what @Aconcagua said. It makes it only a little better for me. I guess its the best a Pseudo-RNG can do... its not really random – Nidhoegger Jun 22 '21 at 08:19
  • 2
    Side note: [`std::bernoulli_distribution`](https://en.cppreference.com/w/cpp/numeric/random/bernoulli_distribution) generates bools directly – Caleth Jun 22 '21 at 08:19
  • @Caleth I bet he didn't wait even a million attempts out of these (because he runs randomization until first 0 appears) – Alexey S. Larionov Jun 22 '21 at 08:20
  • The quality of `rand` varies with implementations, what compiler are you using? The MSVC one has [RAND_MAX of 32767](https://learn.microsoft.com/en-us/previous-versions/398ax69y(v=vs.140)), it might not support 1 in 32768 events too well. –  Jun 22 '21 at 08:20
  • Off-topic: There's absolutely no need to cast the result of `time` – it is converted to appropriate type automatically. Apart from you chose the bad type anyway, `srand` accepts **`unsigned`** `int`... – Aconcagua Jun 22 '21 at 08:20
  • 3
    If your generator has 32 bit periodicity (it probably does), start it at 1 and generate the analysis on the entire sequence. It won't take that long. A linear congruential generator will not get the uniform distribution higher moments anywhere near correct. That's life I'm afraid. Mersenne Twister does slightly better, and is in the C++ standard library from C++11. – Bathsheba Jun 22 '21 at 08:21
  • 2
    `rand()` can be considered deprecated. It is fine for toy random numbers when you do not need quality randomness. If you do expect high quality randomness you are using the wrong tool. Use `` – 463035818_is_not_an_ai Jun 22 '21 at 08:22
  • About [`using namespace std`](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice)... – Aconcagua Jun 22 '21 at 08:23
  • Turns out it was just the compiler so @Nidhoegger 's solution was right, I compiler this program in Visual Studio and it only gave me a max of 15, but in a different online compiler I managed to get up to 29 – popupro Jun 22 '21 at 08:27
  • [rand() Considered Harmful - Stephan T. Lavavej](https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful) – Richard Critten Jun 22 '21 at 08:30
  • You can check twice as many sequences if you check for the zeros as well: `srand(time(nullptr)); auto current = rand() > RAND_MAX/2; for(...) { while(rand() > ... == current) {...} current = !current; /* print new maximum */ }`. – Aconcagua Jun 22 '21 at 08:32
  • Afaik nothing but common sense forbids `rand()` to be `int rand() { return 42; }`, hence there isnt much more to the answer than: You expected `rand` to do something which it is not guaranteed to do. – 463035818_is_not_an_ai Jun 22 '21 at 08:36
  • 2
    @RichardCritten: That presentation is a pretty childish one in my opinion. Donald Knuth (worked on LCGs) is probably one of the finest scientific programmers ever to live, and he was well aware of the deficiencies of a LCG. Off point, but `NULL` is not an abomination. In other words, there's nothing at all wrong with `rand()` so long as you know what you're doing. – Bathsheba Jun 22 '21 at 08:37
  • @Bathsheba things change and sometimes humor helps the message. I also think STL is also owed some respect. – Richard Critten Jun 22 '21 at 08:40
  • @Bathsheba `NULL` has an *implementation-defined* type. It might be `int`, it might be `std::nullptr_t`. You might have code that (wrongly) assumes that it's `void *`. Abominable. – Caleth Jun 22 '21 at 09:11
  • The well known limitation of LCGs demonstrate themselves most clearly in the behaviour of the low order bits of the output. Hence the advice from @Aconcagua to extract high order bit(s) and not % to get the randomness you need. – Ian Cook Jun 22 '21 at 17:29

0 Answers0