This page presents a technique to convert a double returned by Math.random() into a value in a precise range. Also see:
- Random numbers on the AP CS A Exam
- Determine the result of expressions that include
Math.random() - Simulate probability with
Math.random() - Random number exercises
Technique
Make a call to Math.random() and store the result in a variable of the desired type (even if it would not immediately compile).
Write the range of values currently assigned to the variable.
Write the range of values that you want assigned to the variable.
Perform one or more of the three operations below. Each time you perform an operation, update the range currently assigned to the variable.
- Multiply
- Cast to an
int - Add (or subtract)
When you’re done, you are either right and you know you’re right or you’re wrong and you know you’re wrong.
If you’re wrong, start over. If you need to start over, look at your previous attempt to determine what needs to be changed. Do not simply modify your previous attempt. Modifying your previous attempt makes it harder to check that the range is exactly what you want.
Example 1
Declare double r and assign it a value in the range: 0.0 <= r < 5.0
Note: When double values are desired, the top end of the range is usually specified as less than (<).
Step 1
double r = Math.random();
// have: 0.0 <= r < 1.0
// want: 0.0 <= r < 5.0
When we want a double, the upper end of the range is typically specified with <.
Step 2
double r = Math.random() * 5;
// have: 0.0 <= r < 5.0
// want: 0.0 <= r < 5.0
Multiplying by 5 changes the high end of the range to 5.0 (and leaves the low end at 0.0 since 0.0 * 5 is 0.0).
We have what we want, so we’re done and we know we’re right.
Example 2
Declare double r and assign it a value in the range: 7.0 <= r < 12.0
Step 1
double r = Math.random();
// have: 0.0 <= r < 1.0
// want: 7.0 <= r < 12.0
Step 2
double r = Math.random() * 5;
// have: 0.0 <= r < 5.0
// want: 7.0 <= r < 12.0
Multiplying by 5 changes the high end to 5.0.
Step 3
double r = Math.random() * 5 + 7;
// have: 7.0 <= r < 12.0
// want: 7.0 <= r < 12.0
Adding 7 changes both ends of the range.
We have what we want, so we’re done and we know we’re right.
Example 3
Declare int r and assign it a value in the range: 0 <= r <= 5
Note: When int values are desired, the top end of the range is usually specified as less than or equal to (<=).
Step 1
int r = Math.random();
// have: 0.0 <= r < 1.0
// want: 0 <= r <= 5
This statement will not compile because Math.random() returns a double. This is fine because we don’t plan to keep the original statement.
Step 2
int r = Math.random() * 6;
// have: 0.0 <= r < 6.0
// want: 0 <= r <= 5
Multiplying by 6 changes the high end of the range to 6.0.
This statement will not compile either. This is fine because we still aren’t done.
Step 3
int r = (int) (Math.random() * 6);
// have: 0 <= r <= 5
// want: 0 <= r <= 5
When casting to an int, it is the quantity (Math.random() * 6) that we want to cast. Without the parentheses, the cast would apply to the return value from Math.random(), which would always yield 0.
Casting to an int changes the low end of the range to 0.
The high end of the range is more interesting. When we take a number strictly less than 6.0 and cast it to an int, the largest number we will ever get is 5. So the high end of the range becomes <= 5.
We have what we want, so we’re done and we know we’re right.
Example 4
Declare int r and assign it a value in the range: 10 <= r <= 25
Step 1
int r = Math.random();
// have: 0.0 <= r < 1.0
// want: 10 <= r <= 25
Step 2
int r = Math.random() * 16;
// have: 0.0 <= r < 16.0
// want: 10 <= r <= 25
Multiplying changes only the high end.
Step 3
int r = (int) (Math.random() * 16);
// have: 0 <= r <= 15
// want: 10 <= r <= 25
Casting to an int changes both ends.
The high end could be written as < 26, but <= 25 makes more sense for an int.
Step 4
int r = (int) (Math.random() * 16) + 10;
// have: 10 <= r <= 25
// want: 10 <= r <= 25
Adding changes both ends.
We have what we want, so we’re done and we know we’re right.
Example 4
Declare an int variable index. Assign it to a random valid index in non-empty String str.
Step 1
int index = Math.random();
// have: 0.0 <= index < 1.0
// want: 0 <= index <= str.length() - 1
Express the desired range numerically.
The high end of the range could be expressed as < str.length(), but <= str.length() - 1 makes more sense for an int.
Step 2
int index = Math.random() * str.length();
// have: 0.0 <= index < str.length()
// want: 0 <= index <= str.length() - 1
Step 3
int index = (int) (Math.random() * str.length());
// have: 0 <= index <= str.length() - 1
// want: 0 <= index <= str.length() - 1
We have what we want, so we’re done and we know we’re right.
The same approach works for generating a valid random index in an array or in an ArrayList.
It is very common for students to multiply by a variation of str.length() such as (str.length() - 1), not check the resulting range, and lose a point.
It is also common for students to add or subtract after casting, not check the resulting range, and lose a point.