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 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 keywordpublic 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; } }
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.
The creation of the random number generator has been done globally for the class and not inside theimport 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; } }
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.
The application for one simulation of the game is now as follows:class GameResult { int gameLength; String winner; GameResult(int gameLength, String winner) { this.gameLength = gameLength; this.winner = winner; } }
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; } }
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 theimport 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; i0 && 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; } }
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