Random Numbers With Math.random()
Many applications in diverse domain areas, such as games, cryptography, or simulations, require a way to randomize events. For instance, the flip of a coin, the pull of a slot machine's handle, or the price change of a stock index. In this tutorial we will explore different options in the Java API for generating random numbers (building a random number generator).
In Java there are two classes that can be used to generate random numbers: java.util.Random and java.lang.Math. Math has several static convenience methods that will handle most of one's random number needs. If you need more options, Random adds additional capabilities that we will cover toward the end of this tutorial.
- Computers Don't Generate Truly Random Numbers
Computers cannot create true random numbers according to strict mathematical definitions but for most general computing needs this is not a practical limitation. The pseudorandom numbers generated by computers will be a close enough approximation. (If it is not sufficient for your purposes, consult a mathematician!)
- Random Number Generation Example
To start, let's look at a simple example.
double randomValue = Math.random();
What did you get? I guarantee that it was a number between 0.0 and 1.0 (including 0.0 but not including 1.0). I got "0.8416533062276157." Run it again. You probably got a different number. Pretty easy, right?
So, the default behavior of Math.random() is to generate a double in the interval [0 1).
- Build a Custom Random Number Generator
Generating numbers in the range 0.0 to 1.0 has limited value, so let's see how we can define the range that we'll pull our random number from the range 0.0 to 10.0 (including 0.0 but not including 10.0) or [0 10). We do this by multiplying the generated random double by 10. This is called scaling the range.
double randomValue = Math.random() * 10;
I got "5.796280106258913" when I ran this example.
So, let's change the interval to be 1.0 to 11.0 [1 11). This is known as shifting the range.
double randomValue = 1 + Math.random() * 10;
Running this example, I got "7.6887892451197315." It is hard to see any difference, so let's prove that we are shifting the range. Let's generate a random number from 100.0 to 200.0 or [100 200).
double randomValue = 100 + Math.random() * 100;
I got 149.1804870735694. (I won't say that I told you so.)
- Generate Random Integers
If one actually needs an int instead of a double, simply convert the returned double to an int by casting it.
int randomInt = 1 + (int)(Math.random() * 50);
This will truncate the generated double and return an int between 1 and 50. I got "19." Don't forget the parentheses around the Math.random() * 50. This is required, otherwise the double will be truncated before the multiplication operation!
Java Random Numbers With Random Class
Occasionally, you may need more help generating random numbers than Math.random() can give. In these cases, you can turn to java.util.Random
Seeding Random Number Generation
So far, we have been asking for random numbers and expecting them to be truly random (or at least as random as a computer can produce). This works well except when we are testing and debugging code that manipulates randomly generated numbers.
For instance, if you are writing a method that "rolls" two 6-sided dice and returns the resulting sum, how do you know if your calculation is correct? Each time you call the method, each die will return a random number. For this and other scenarios where you want random number generation to always return the same sequence, you can seed the generator with a long.
Let's take a look at generating random numbers with Random and how we can define the seed for testing and debugging purposes.
Random randomizer = new Random(1L);
//remember longs are appended with L
First, we create a new Random instance and pass in our desired seed value of 1L. Any two instances of Random that have the same seed will always return the same "random" numbers in the exact same sequence.
int randomInt = randomizer.nextInt();
Next, we generate our random number, randomInt. Notice we haven't defined an interval, as we did with Math.random(). Random.nextInt() returns a number between (approximately) -2.1 billion and 2.1 billion. (This is based on the size an int can hold.)
randomInt = Math.abs(randomInt);
Next, we pass randomInt through Math.abs(). This, of course, eliminates negatives.
randomInt = (randomInt % 6) + 1;
This step looks similar to, but not exactly like, the scaling and shifting we did with Math.random(). The idea is the same, we want to customize our random number's range (from 2.1 billion to 6). So, we first find randomInt modulo 6. This gives us a number between 0 and 5. Finally, we shift the result up 1, giving us a final range of 1 to 6. Time to take a break!
Random Class Wrap-Up
When you are not debugging or testing code, you can randomly seed your random number generator by passing in the long from System.currentTimeMillis(). This grabs a long from the system's clock.
As you saw in the above examples, using Math.random() is significantly simplier than using Random. Scenarios when Random is helpful:
- One needs to seed the random number sequence.
- One wants to easily get a random byte.
- One needs a random number from a Gaussian distribution.
Now you are properly equipped to whip up virtually any random number you may need in your coding projects. Let's put your knowledge of random number generation to use by writing a set of classes to simulate rolling dice.
Random Number Exercise: Dice Roller
If you started at the beginning, you have made it through a good portion of the Focus on Java Java Programming Tutorial. In addition to basic language features such as conditionals and operators, you have learned about classes and methods. Now, let us put what we have learned to use. This is the first of several programming exercises in the tutorial. Each is designed to help you apply the lessons and concrete them into your mind.
Write a class named dice.Die that represents a single die roll and can return its number of sides and its rolled value. The class should be immutable—meaning it must be instantiated with all of its properties defined in its constructor and these properties must not be modifiable.
Die must have one public constructor that defines its number of sides and its rolled value via parameters.
public Die(int numberOfSides, int valueRolled)
Die must have two public methods for getting its properties:
public int getValueRolled() public int getNumberOfSides()
Next, write a class named dice.DieRoller. It must have one public method with the following signature:
public Die roll(int sides)
When called, roll() must return a new instance of dice.Die that represents the value rolled. This number must be a random int in the range 1 to sides where sides is the number of sides the die has (and that was passed into roll() as an argument). Feel free to use either Math.random() or Random class.
Finally, write a dice.DieRollerExample class that uses Die and DieRoller to roll different dice combinations. For instance, a 6 sided die, two 6 sided dice, a 20 sided die, etc. For extra credit, write a simple craps game based on the roll of two dice.
0 comments:
Post a Comment