|
There are two possible ways to randomly generate numbers:
java.lang.Math contains the method
random() that returns a uniformly
distributed pseudorandom float value between 0.0 and 1.0.
java.util.Random provides methods to generate
pseudorandom numbers. You first create a new random generator with the
Random method. This makes available methods to compute
the next element in the current random number generator's sequence. Commonly
used methods are the following:
nextInt() returns the next pseudorandom, uniformly
distributed int value.nextDouble() returns the next pseudorandom, uniformly
distributed double value between 0.0 and 1.0.nextGaussian() returns the next pseudorandom, normally
distributed double value with mean
0.0 and standard deviation 1.0
public static int[] toss1() {
Random R = new Random();
int number;
number = (R.nextInt() % 2 == 0) ? -1 : 1;
}
return number;
}
public static int toss2() {
if (Math.random() < 0.5) {
return -1;
}
else {
return 1;
}
}
In the first method we generate each time a new integer, carry out
integer division with 2, and replace a reminder of 0 by -1.
The keyword static turns both methods in what is called
a class method, which is discussed later.
With these utilities we can easily implement a method to
randomly generate 1s and -1s. Below we present a method to generate an
array of randomly chosen 1s and -1s. Experimentation reveals that in
this case you better use the
java.util.Random class for efficiency reasons.
Random R = new Random();
public static int[] toss(int n) {
int[] numbers = new int[n];
for (int i=0; i < numbers.length; i++) {
numbers[i] = (R.nextInt() % 2 == 0) ? -1 : 1;
}
return numbers;
}
Now that we know how 1s and -1s can be generated efficiently, we can concentrate on the gambling game itself. In this section we write down the kind of lines of Java code that correspond with different phases in the simulation of one game. We start with initializing John's and Sarah's amount of money:
We flip the coin once and update the amount of money John and Sarah have:int johnsDollars = 5, sarahsDollars = 10;
Random R = new Random(); int profit; profit = (R.nextInt() % 2 == 0) ? -1 : 1; johnsDollars -= profit; sarahsDollars += profit;
Because we are interested in the length of the game, we introduce the variablejohnDollars > 0 && sarahsDollars > 0
numberOfTosses that counts
the number of times the coin is flipped. This variable is
initialized at value 0 and is updated during the repetitive process.
The repetition is the following while-loop:
while (johnDollars > 0 && sarahsDollars > 0) {
profit = (R.nextInt() % 2 == 0) ? -1 : 1;
johnDollars -= profit;
sarahsDollars += profit;
numberOfTosses++;
}
game and assume that
it is called with the initial amounts of money of the
players as actual arguments and returns the length of
the game.
import java.util.*;
public class OneGame1stVersion {
static Random R = new Random();
public static void main(String[] args) {
int onegame = game(5,10);
System.out.println("Game Length is " + onegame);
}
static int game(int johnsDollars, int sarahsDollars) {
int numberOfTosses = 0, profit = 0;
while (johnsDollars > 0 && sarahsDollars > 0) {
profit = (R.nextInt() % 2 == 0) ? -1 : 1;
johnsDollars -= profit;
sarahsDollars += profit;
numberOfTosses++;
}
return numberOfTosses;
}
}
The creation of the random number generator has been done globally for the
class and not inside the game to avoid bias
when this method is applied many times in a simulation.
To declare such a class variable you use the keyword static.
Similarly, with the keyword static, the game method is declared
a class method. You do not have to create an object to be able to call this method.
The current application only shows the length of the game, but not who wins. To add this information, we introduce a new class to hold the length of the game and the name of the winner.
class GameResult {
int gameLength;
String winner;
GameResult(int gameLength, String winner) {
this.gameLength = gameLength;
this.winner = winner;
}
}
The application for one simulation of the game is now as follows:
import java.util.*;
public class OneGame {
static Random R = new Random();
public static void main(String[] args) {
GameResult onegame = game(5,10);
System.out.println("Game Length is " + onegame.gameLength);
System.out.println("Winner is " + onegame.winner);
}
static GameResult game(int johnsDollars, int sarahsDollars) {
int numberOfTosses = 0, profit = 0;
while (johnsDollars > 0 && sarahsDollars > 0) {
profit = (R.nextInt() % 2 == 0) ? -1 : 1;
johnsDollars -= profit;
sarahsDollars += profit;
numberOfTosses++;
}
GameResult result = (sarahsDollars > 0) ?
new GameResult(numberOfTosses, "Sarah") :
new GameResult(numberOfTosses, "John");
return result;
}
}
import java.util.*;
public class Simulation {
static Random R = new Random();
static int numberOfGames = 5000;
public static void main(String[] args) {
GameResult[] games = new GameResult[numberOfGames];
for (int i=0; i 0 && SarahsAmountOfMoney > 0) {
profit = (R.nextInt() % 2 == 0) ? -1 : 1;
JohnsAmountOfMoney -= profit;
SarahsAmountOfMoney += profit;
numberOfTosses++;
}
GameResult result = (SarahsAmountOfMoney > 0) ?
new GameResult(numberOfTosses, "Sarah") :
new GameResult(numberOfTosses, "John");
return result;
}
}
One remark about the Java code: Java has a built-in garbage collector that is
automatically invoked but runs on low-priority.
However, during execution of the for-loop in which all games are
simulated the garbage collector may get no chance to remove the objects created
by the game method and which are not needed anymore, and program
execution may stop because of lack of memory. For this reason we call
inside the for-loop each time after 1000 iterations the garbage collector
via the gc method of the System class.
The output of a run of three simulations of each 5000 games is shown below:
The numerical results are in good comparison with the theoretical results.Average game length = 50.079 Proportion that Sarah won = 0.6654 Average length of games won by Sarah = 42.0171 Average length of games won by John = 66.1112 Average game length = 50.1888 Proportion that Sarah won = 0.6656 Average length of games won by Sarah = 42.2975 Average length of games won by John = 65.8959 Average game length = 49.9364 Proportion that Sarah won = 0.6664 Average length of games won by Sarah = 41.7017 Average length of games won by John = 66.3861