Learning C++, Random Number Generator

Thread Starter

sailmike

Joined Nov 11, 2013
147
I'm trying to use "rand" and "srand" to generate random numbers between 1 and 2 and then assigning heads to 1 and tails to 2 to simulate a coin flip. The explanation is probably just a bit of math I think. I need a better explanation of the following line:

return rand() % (high - low + 1) + low;

I'm not sure how "rand()" works or the use of %. I've attached the program as a text file.

Thanks,
Mike
 

Attachments

nsaspook

Joined Aug 27, 2009
6,278
The function srand(key) provides the 'seed' that rand will use to generate a repeating sequence of 'random' numbers.
% is the modulus operator.
http://www.cprogramming.com/tutorial/modulus.html

You would get the remainder of the low binary bits from rand() % some large number.
The stock C++ rand modulo operation is not a very good generator if you plan for the coin flip to be truly random. The low bit distribution is very weak.
 

vpoko

Joined Jan 5, 2012
267
rand() will return a pseudo-random integer between 0 and some large number (how large depends on the value of a constant, RAND_MAX, found in stdlib.h).

% is the modulo operator. "a % b", read as "a mod b", means divide a by b, and ignoring the whole part, return the remainder.

For example 7 % 4 means divide 7 by 4 and return the remainder, which is 3. We do this intuitively with clock math. When an analog clock reads 10:00, you know that adding 5 hours will make it show 3:00. That's because 10 + 5 = 15, and 15 % 12 = 3.

The point of it is to place an upper bound on some number and have it "start from the beginning" if it gets above that number. By doing "rand() % n" you'll get a number between 0 and n-1 (not with a perfectly equal probability for various reasons).

The code you have places both an upper and a lower bound (returns a number between low and high). It might look confusing, but once you consider order of operations, it makes sense. First what's inside the parenthesis (high - low + 1) is evaluated, then the % is evaluated, and finally low is added to the result. If you're still confused, pick low and high numbers in your head, then pick a "random" number (also in your head) somewhat bigger than the high, and work out the math on paper.
 
Last edited:

Kermit2

Joined Feb 5, 2010
4,158
for more random than a single rand function, place the rand function in a for next loop that uses a rand function to determine the number of loops and then take the your random number from the rand function after it has been executed and discarded a random number of times before returning the value.
 

Papabravo

Joined Feb 24, 2006
12,397
for more random than a single rand function, place the rand function in a for next loop that uses a rand function to determine the number of loops and then take the your random number from the rand function after it has been executed and discarded a random number of times before returning the value.
There is no reason to suspect the result would have better random properties than the underlying psedo-random sequence, although it may be tempting to posit that suggestion.
 

vpoko

Joined Jan 5, 2012
267
There is no reason to suspect the result would have better random properties than the underlying psedo-random sequence, although it may be tempting to posit that suggestion.
Indeed. I think randomness is a an area where intuition tends to fail.

In any case sailmike, for your purposes, the stock c rand() function is more than random enough.
 
Last edited:

Thread Starter

sailmike

Joined Nov 11, 2013
147
I forgot to mention that my code doesn't compile. There are some errors:


warning C4244: 'argument': conversion from 'time_t' to 'unsigned int', possible loss of data
error C2446: '==': no conversion from 'int' to 'int (__cdecl *)(int,int)
note: Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
error C2040: '==': 'int (__cdecl *)(int,int)' differs in levels of indirection from 'int'

Whoops, I just noticed that I declared heads and tails double numbers instead of integers. It still doesn't compile though.

Thanks,
Mike
 

vpoko

Joined Jan 5, 2012
267
Sailmike, randrange is a function, so you'd have to change if (randrange == 1) to if (randrange(1, 2) == 1).

But because you call randrange above, and want to reuse the result instead of re-evaluating, what you need do is create a variable to assign the return value of randrange the first time you call it, and then compare that variable in the if statement.
Code:
// Somewhere outside your for loop.
int rng;

// Inside your for loop.
rng = randrange(1, 2);
cout << rng << '\n';
if (rng ==1)
...
 
Last edited:

Thread Starter

sailmike

Joined Nov 11, 2013
147
That compiled and ran fine. Thank you!

Could part of the problem be that I had the numbers backwards? As in randrange(3, 2) instead of randrange(2, 3)?

I understand your explanation.

Mike
 
Last edited:

vpoko

Joined Jan 5, 2012
267
That compiled and ran fine. Thank you!

Could part of the problem be that I had the numbers backwards? As in randrange(3, 2) instead of randrange(2, 3)?

I understand your explanation.

Mike
Let's work out what happens with randrange(3, 2)...

The statement would look like: return rand() % (2 - 3 + 1) + 3;
The part inside the parenthesis would evaluate to 0, so it would try rand() % 0 (before adding the 3), and you can't mod by 0 for the same reason that you can't divide by 0, so it would fail at runtime with a divide-by-zero error or something akin to it. It wouldn't fail to compile, though, since it wouldn't evaluate the function until it's actually called, which doesn't happen until you run the program.
 
Last edited:
Top