# Learning C++, Random Number Generator

Discussion in 'Programmer's Corner' started by sailmike, Aug 15, 2015.

1. ### sailmike Thread Starter Member

Nov 11, 2013
143
3
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

File size:
549 bytes
Views:
4
2. ### nsaspook AAC Fanatic!

Aug 27, 2009
3,011
2,356
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.

3. ### Papabravo Expert

Feb 24, 2006
10,340
1,850
A good random number generator is an extraordinarily hard thing to get right. Knuth has written exhaustively on the subject in Volume 2 of, The Art of Computer Programming

http://www.informit.com/articles/article.aspx?p=2221790

Try the exercises if you have the intestinal fortitude.

4. ### vpoko Member

Jan 5, 2012
258
47
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: Aug 16, 2015
5. ### Kermit2 AAC Fanatic!

Feb 5, 2010
3,847
963
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.

6. ### Papabravo Expert

Feb 24, 2006
10,340
1,850
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.

7. ### vpoko Member

Jan 5, 2012
258
47
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: Aug 16, 2015

Feb 24, 2006
10,340
1,850
9. ### sailmike Thread Starter Member

Nov 11, 2013
143
3
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

10. ### vpoko Member

Jan 5, 2012
258
47
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 (Text):
1. // Somewhere outside your for loop.
2. int rng;
3.
4. // Inside your for loop.
5. rng = randrange(1, 2);
6. cout << rng << '\n';
7. if (rng ==1)
8. ...

Last edited: Aug 17, 2015
11. ### sailmike Thread Starter Member

Nov 11, 2013
143
3
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)?

Mike

Last edited: Aug 17, 2015
12. ### vpoko Member

Jan 5, 2012
258
47
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: Aug 17, 2015

Apr 14, 2014
11
0

Apr 11, 2010
2,900
876