How Does C++ Handle Random Number Generation in Coin Toss Simulations?

Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
10 replies · 2K views
Lord Anoobis
Messages
131
Reaction score
22
Homework Statement
Write a function named coinToss that simulates the tossing of a coin and generates the number of tosses as input by the user.
Relevant Equations
None.
The program works as intended.
C++:
#include <iostream>
#include <ctime>
#include <cstdlib>

int coinToss ();int main ()
{
    int tosses, result;
    std::count << "How many coin tosses? ";
    std::cin >> tosses;
    size_t seeder = time(0);
    srand(seeder);
    
    for (int i = 0; i < tosses; i++)
    {
        result = coinToss ();
        std::count << result << "\n";
    }
    
    return 0;
}

int coinToss ()
{
    int toss;
    toss = rand() % 2 + 1;
    return toss;
}

What I would like to know is why when the randomization is placed within the function (which is what I had done first) does it spit out either all 1s or all 2s?
C++:
int coinToss ()
{
    int toss;
    size_t seeder = time(0);
    srand(seeder);
    toss = rand() % 2 + 1;
    return toss;
}
 
on Phys.org
When you initialize the pseudo-random number generator with the srand(seeder) statement, this starts off a new sequence of pseudo-random numbers. For the same value of seeder, you will always get the same sequence of numbers. The loop runs so fast, that the value of time(0) is always the same each time through the loop. I think the value of time(0) is in milliseconds, but I'm not sure. So you always intialize with the same value of seeder, so the rand() statement always gives you the same number. Try printing out the value of time(0).

Edit: Actually the value of time(0) is in seconds since 00:00 hours, Jan 1, 1970 UTC, so the loop can run many,many times in 1 second.
 
Last edited:
Tried that just now. The value of time(0) stays the same in both cases but with different results. As long as seeder and its accomplices are part of the function its always 1s or 2s. Weird.
 
phyzguy said:
It's not weird, it's completely understandable. What part of my explanation didn't you get?
I'm not quite sure why the two cases behave so differently if the value of time(0) does not change for each repetition of the loop in both cases.
 
In the case where the srand(seeder) statement is outside the loop, you get:

Initialize pseudo-random number generator
Pseudo-random number 1
Pseudo-random number 2
Pseudo-random number 3
...

In the case where the srand(seeder) statement is inside the loop, you get:

Initialize pseudo-random number generator
Pseudo-random number 1
Initialize pseudo-random number generator
Pseudo-random number 1
Initialize pseudo-random number generator
Pseudo-random number 1
...
 
I just had it generate randoms only. I was under the impression that in the case of it being in the loop it would generate a different number on each pass regardless.
 
Lord Anoobis said:
I just had it generate randoms only. I was under the impression that in that case it would generate a different number on each pass regardless.
No! It's a pseudo-random number generator. You should read about how they work. It is deterministic. For the same seed value, it will always generate the same sequence of numbers.
 
phyzguy said:
No! It's a pseudo-random number generator. You should read about how they work. It is deterministic. For the same seed value, it will always generate the same sequence of numbers.
Yeah, I can see now what you meant in the first post. Valuable lesson learned and thanks.
 
On another note, when I was testing it earlier today multiple times, an even number of tosses always gave 2s and an uneven number 1s, from 1 all the way to 20 and on more than one attempt. It was only when I used say, 10, a number of times in succession that it eventually broke formation. If ever there was a case of coincidence further confounding the issue.
 
Since you already start doubting your random number generation: I do not know about your specific observation, but rand() is generally not an appropriate way to generate random numbers. Not for scientific purposes. Absolutely not for cryptography. Probably not even for computer games with dice rolling.

Since version C++11, C++ features proper random number generators out of the box. I highly recommend using them for all cases (except cryptography - just don't do cryptography at all). The Mersenne-Twister algorithm is a good default. Here's your code using this RNG, instead:
C++:
#include <ctime>
#include <iostream>
#include <random>// Mersenne-Twister generator with current time as seed.
std::mt19937 randomNumberGenerator(time(0));

// Distribution represeting a coin: Gets 1 or 2,
// depending on the random number passed.
std::uniform_int_distribution<> coinDistribution(1, 2);int coinToss() {
    return coinDistribution(randomNumberGenerator);
}int main() {
    int tosses, result;
    std::count << "How many coin tosses? ";
    std::cin >> tosses;

    for (int i = 0; i < tosses; i++) {
        result = coinToss();
        std::count << result << "\n";
    }

    return 0;
}