# Random Numbers and Computer Simulations

• Introduction

• Computer Simulation is NOT a game, but is a commonly used technique to study unknown complex processes

• In a computer simulation, you generate random events and evaluate their outcome

• Motivational Example

• Problem:

 Write a computer program to find the probability that tossing 2 dice will make a total of 8.

• If you have had Probability Theory, you can compute the answer...

8 comes up when we roll one of the following:

• die1 = 2 and die2 = 6
• die1 = 3 and die2 = 5
• die1 = 4 and die2 = 4
• die1 = 5 and die2 = 3
• die1 = 6 and die2 = 2

The probability of each event is:

```     1     1     1
--- x --- = ---
6     6     36
```

• What if you did not have Probability Theory or the problem is more complicated than a simple dice roll...

• We will to learn a technique that scientists from various disciplines to solve complicated problem.

This technique has a fancy name like Monte Carlo Method

The basis of this technique is to use many (say N) computer experiments - each one with a random outcome - to represent what would happen in reality.

By counting the successes among the N experiments, we can obtain valuable information,

• But first, we must learn to generate random numbers

• Random Numbers

• Random numbers are a sequence of numbers drawn from a certain range/domain and each outcome is unpredicatble

• Examples:

• Rolling a die will generate randoms from the range {1, 2, 3, 4, 5, 6}

• The outcome of "Cash 3" drawing is a random number between 000 and 999.

• Psuedo Random Numbers

• Psuedo random numbers are a sequence of numbers drawn from a certain range/domain and each outcome is completely predicatble

However, the "distribution" (i.e., behavior) of the Psuedo random numbers is virtually identical to random numbers.

• Psuedo random numbers are "generated" by psuedo random number generators

• A psuedo random number generator is a Mathematical function that generate random number from a given distribution - usually decimal numbers between (0, 1).

• The subject of psuedo random number generators is outside the scope of this class; we will only learn to USE a psuedo random number generator

• Generating Psuedo Random Numbers

• You may have a RAND function button on your calculator - each time when you press this button, you get a different "random" number (but it is in fact a "psuedo" random number.

• The Java library has provide us with this class that can be used to generate "psuedo" random numbers:

• Random

• Here is the online documentation for the Random class: click here

• The methods that we need are:

 ``` nextDouble(): Returns the next pseudorandom, uniformly distributed double value between 0.0 and 1.0 from this random number generator's sequence. nextInt(int n): Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and n (exclusive), (i.e., between 0 and n-1) drawn from this random number generator's sequence. ```

• Notice that these methods are instance methods (no keyword static).

So we must construct a Random object and use the object to invoke these method.

• NOTE: the phrase "this random number generator" refers to the Random object on which the methods are invoked...

• Example: how to generate integer and decimal random numbers

 ```import java.util.Random; public class Random1 { public static void main(String[] args) { int i; Random gen = new Random(); /* ----------------------------------------------- gen.nextInt(6) generate random integers between 0 and 5 ----------------------------------------------- */ System.out.println("Testing gen.nextInt(6):"); for ( i = 0; i < 10; i++ ) { System.out.println("Random number in [0, 6) = " + gen.nextInt(6) ); } /* ----------------------------------------------- gen.nextDouble() generate random decimal numbers between 0 and 1 ----------------------------------------------- */ System.out.println("Testing gen.nextDouble():"); for ( i = 0; i < 10; i++ ) { System.out.println("Random number in [0, 1) = " + gen.nextDouble() ); } } } ```

• NOTE:

You need to inport java.util.Random before you can use the class Random

• An N-sided Die class

• We can use the Random class to write a class that functions like an N-sided die

• What exactly is an N-sided die ?

• The most commonly used die is a 6-sided die

When a 6-sided die is casted (tossed), the outcome of the cast is one of the numbers {1, 2, 3, 4, 5, 6}.

• An N-sided die is a die with N sides

When a N-sided die is casted (tossed), the outcome of the cast is one of the numbers {1, 2, ..., N}.

• Designing the public interface for the N-sided Die class

• We need to name the class first: "Die" is a good name...

 ``` public class Die { ... } ```

• What now ?

We need to be able to construct a die with given number of sides

So we need a constructor that take an integer number (# sides):

 ``` public class Die { public Die(int numberSides) { .... } } ```

• What next ?

We need to be able to cast the die.

So we need a method "cast" - does this method need any information to do its task ?... No... so no parameters...

Does this "cast" method return anything ?... Yes: the outcome of the die roll !

 ``` public class Die { public Die(int numberSides) { .... } public int cast() { .... } } ```

• Do we need more methods ?

• We can make a die with "Die()"
• We can roll a die with "cast()"

No more methods are necessary

• What instance variables do we need ?

Programs need information to do their job.

What information does the methods in the Die class need to perform its job ?

 NOTE: the computer can never make the real thing; it can only make a representation - the representation must be capable to perform all the tasks that the real thing can do. In the case of a die: the die must return a random number between 1 and n when the die is "casted"

1. In order to return a random number: we need to make a Random object.

2. In order to return a random number between 1 and n: we can use the expression: 1 + nextInt(n) - so we have a integer variable to remember n.

So we need the following instance variables in Die for the Die class to do its job:

 ``` import java.util.Random; public class Die { public Die(int numberSides) { .... } public int cast() { .... } private Random generator; private int sides } ```

• NOTE: now that we want to define a Random object in this class, we need to import its definition !

• Notice that it is the constructor's duty to initialize the instance variables (here: generator and sides ) !!!

• Implementing (writing the methods of) the N-sided Die class

• Write Constructor Die(n)

• Input: integer n = # sides of the die

• Effect: "make" an n-sided die

 NOTE: as mentioned before, the computer can never make the real thing; it can only make a representation - the representation must be capable to perform all the tasks that the real thing can do A constructor always must initialize every instance variable so that the object can do its job.

 ``` import java.util.Random; public class Die { public Die(int numberSides) { generator = new Random(); // Construct a Random object sides = numberSides; // Remember the # sides } public int cast() { .... } private Random generator; private int sides } ```

• Write the method cast()

• Input: no input

• Effect: "cast" the n-sided die - it returns a random number between 1 and n

 ``` import java.util.Random; public class Die { public Die(int numberSides) { generator = new Random(); // Construct a Random object sides = numberSides; // Remember the # sides } public int cast() { return(generator.nextInt(sides)); } private Random generator; private int sides } ```

• NOTE: you can clearly see why the constructor must initialize BOTH variables generator and sides - because cast() uses BOTH variables to do its job !!!

• Example Program: (Demo above code)

• Using the Die class in a complicated experiment

• Problem:

 Roll a 6-sided die What is the average number of rolls needed to roll a 6 ?

• How would you solve this problem with a real die ?

Do the following:

 Roll a 6-sided die, check the roll, if roll = 6, stop, otherwise keep rolling - all the while, keep a tally on the number of times rolled. Do this experiment over and over again for many many times; Take the average on the number of rolls needed to roll a 6

Good news: the computer can do this and in a fraction of a sec !!!
Hey, that's why computer science can be useful :-)

• Psuedo program to solve this problem: (always write a "psuedo" program to check that the solution will work !)

 ``` // Version 1: don't worry about the variable types, // Just use them and figure out later what their types are.... // Don't worry about "Java"; but BE PRECISE ! // Perform the experiment for n times for ( i = 1; i <= n; i++ ) { "Roll a die d until 6 shows and keep a tally on # rolls"; } "Find the average number of rolls in n experiments"; ```

• Refinement 1: compute the average

• In order to compute the average, we need to:

• Keep a running total of the number of rolls of the die (totalNumRolls)
• Keep a number of tries (numTries)

• The average number of rolls is then equal to:
```         (double) totalNumRolls/numTries
```

The modified program with specifics on how to compute the average:

 ``` // Version 1: solve the "compute average problem: // Things will get more like "Java"; and ALWAYS BE PRECISE ! int totalNumRolls = 0; int numTries = 0; for ( i = 1; i <= n; i++ ) { "Roll a die d until 6 shows"; totalNumRolls = totalNumRolls + (# rolls needed)"; numTries++; } System.out.println( (double) totalNumRolls/numTries ); ```

• Refinement 2: roll the die until 6 comes up, while keeping a tally on the # rolls !!!

• To roll the die, we need to construct a Die object - let's give it the name: myDie

Make sure it's a 6-sided die !

• To roll the die myDie, we invoke: myDie.roll()

• To keep a running count on the number of rolls of the die, we need an integer variable - let's give it the name: numOfRolls

• To remember the outcome of a (one) roll of the die, we need an integer variable - let's give it the name: outcomeOfThisRoll

"Rolling myDie, recording the outcome and keep a running count of the number of times rolled" is done by using:

```        outcomeOfThisRoll = myDie.cast();
numOfRolls++;
```

• We roll until 6 comes up, we can do this with this while statement:
```	while ( outcomeOfThisRoll != 6 )
{
....
}
```

The modified program with specifics on rolling a die until 6 shows, while keeping a running count on the numbers of rolls is:

 ``` // Version 2: solve the "rolling a die until..." problem // Things will get more like "Java"; and ALWAYS BE PRECISE ! int totalNumRolls = 0; int numTries = 0; Die myDie = new Die(6); // construct a 6-sided die int numOfRolls; int outcomeOfThisRoll; for ( i = 1; i <= n; i++ ) { numOfRolls = 0; // Reset numOfRolls for next experiment /* ===================================================== Roll the die for the first time in this experiment ===================================================== */ outcomeOfThisRoll = myDie.cast(); numOfRolls++; /* ===================================================== Keep rolling the die until 6 shows ===================================================== */ while ( outcomeOfThisRoll != 6 ) { outcomeOfThisRoll = myDie.cast(); // Roll the die again numOfRolls++; // Keep running count ! } /* ============================================================== Update information to compute the average number of rolls/try ============================================================== */ totalNumRolls = totalNumRolls + numOfRolls; numTries++; } System.out.println( (double) totalNumRolls/numTries ); ```

• Example Program: (Demo above code)

• Self Check

• How do you use a random number generator to simulate the toss of a coin?

```	int n = generator.nextInt(2); // 0 = heads, 1 = tails