0% found this document useful (0 votes)
34 views

Chapter 87: Random Number Generation: Section 87.1: Pseudo Random Numbers

The document discusses various methods for generating random numbers in Java including the built-in Random class, ThreadLocalRandom, and SecureRandom. It also covers generating random numbers within a specific range, without duplicates, and using the Apache Commons Lang library.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views

Chapter 87: Random Number Generation: Section 87.1: Pseudo Random Numbers

The document discusses various methods for generating random numbers in Java including the built-in Random class, ThreadLocalRandom, and SecureRandom. It also covers generating random numbers within a specific range, without duplicates, and using the Apache Commons Lang library.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 4

Chapter 87: Random Number Generation

Section 87.1: Pseudo Random Numbers


Java provides, as part of the utils package, a basic pseudo-random number generator, appropriately named
Random. This object can be used to generate a pseudo-random value as any of the built-in numerical datatypes (int,
float, etc). You can also use it to generate a random Boolean value, or a random array of bytes. An example usage
is as follows:

import java.util.Random;

...

Random random = new Random();


int randInt = random.nextInt();
long randLong = random.nextLong();

double randDouble = random.nextDouble(); //This returns a value between 0.0 and 1.0
float randFloat = random.nextFloat(); //Same as nextDouble

byte[] randBytes = new byte[16];


random.nextBytes(randBytes); //nextBytes takes a user-supplied byte array, and fills it with random
bytes. It returns nothing.

NOTE: This class only produces fairly low-quality pseudo-random numbers, and should never be used to generate
random numbers for cryptographic operations or other situations where higher-quality randomness is critical (For
that, you would want to use the SecureRandom class, as noted below). An explanation for the distinction between
"secure" and "insecure" randomness is beyond the scope of this example.

Section 87.2: Pseudo Random Numbers in Specific Range


The method nextInt(int bound) of Random accepts an upper exclusive boundary, i.e. a number that the returned
random value must be less than. However, only the nextInt method accepts a bound; nextLong, nextDouble etc.
do not.

Random random = new Random();


random.nextInt(1000); // 0 - 999

int number = 10 + random.nextInt(100); // number is in the range of 10 to 109

Starting in Java 1.7, you may also use ThreadLocalRandom (source). This class provides a thread-safe PRNG (pseudo-
random number generator). Note that the nextInt method of this class accepts both an upper and lower bound.

import java.util.concurrent.ThreadLocalRandom;

// nextInt is normally exclusive of the top value,


// so add 1 to make it inclusive
ThreadLocalRandom.current().nextInt(min, max + 1);

Note that the official documentation states that nextInt(int bound) can do weird things when bound is near 230+1
(emphasis added):

The algorithm is slightly tricky. It rejects values that would result in an uneven distribution (due to
the fact that 2^31 is not divisible by n). The probability of a value being rejected depends on n. The worst

GoalKicker.com – Java® Notes for Professionals 512


case is n=2^30+1, for which the probability of a reject is 1/2, and the expected number of iterations
before the loop terminates is 2.

In other words, specifying a bound will (slightly) decrease the performance of the nextInt method, and this
performance decrease will become more pronounced as the bound approaches half the max int value.

Section 87.3: Generating cryptographically secure


pseudorandom numbers
Random and ThreadLocalRandom are good enough for everyday use, but they have a big problem: They are based on
a linear congruential generator, an algorithm whose output can be predicted rather easily. Thus, these two classes
are not suitable for cryptographic uses (such as key generation).

One can use java.security.SecureRandom in situations where a PRNG with an output that is very hard to predict is
required. Predicting the random numbers created by instances of this class is hard enough to label the class as
cryptographically secure.

import java.security.SecureRandom;
import java.util.Arrays;

public class Foo {


public static void main(String[] args) {
SecureRandom rng = new SecureRandom();
byte[] randomBytes = new byte[64];
rng.nextBytes(randomBytes); // Fills randomBytes with random bytes (duh)
System.out.println(Arrays.toString(randomBytes));
}
}

Besides being cryptographically secure, SecureRandom has a gigantic period of 2160, compared to Randoms period of
248. It has one drawback of being considerably slower than Random and other linear PRNGs such as Mersenne
Twister and Xorshift, however.

Note that SecureRandom implementation is both platform and provider dependent. The default SecureRandom
(given by SUN provider in sun.security.provider.SecureRandom):

on Unix-like systems, seeded with data from /dev/random and/or /dev/urandom.


on Windows, seeded with calls to CryptGenRandom() in CryptoAPI.

Section 87.4: Generating Random Numbers with a Specified


Seed
//Creates a Random instance with a seed of 12345.
Random random = new Random(12345L);

//Gets a ThreadLocalRandom instance


ThreadLocalRandom tlr = ThreadLocalRandom.current();

//Set the instance's seed.


tlr.setSeed(12345L);

Using the same seed to generate random numbers will return the same numbers every time, so setting a different
seed for every Random instance is a good idea if you don't want to end up with duplicate numbers.

GoalKicker.com – Java® Notes for Professionals 513


A good method to get a Long that is different for every call is System.currentTimeMillis():

Random random = new Random(System.currentTimeMillis());


ThreadLocalRandom.current().setSeed(System.currentTimeMillis());

Section 87.5: Select random numbers without duplicates


/**
* returns a array of random numbers with no duplicates
* @param range the range of possible numbers for ex. if 100 then it can be anywhere from 1-100
* @param length the length of the array of random numbers
* @return array of random numbers with no duplicates.
*/
public static int[] getRandomNumbersWithNoDuplicates(int range, int length){
if (length<range){
// this is where all the random numbers
int[] randomNumbers = new int[length];

// loop through all the random numbers to set them


for (int q = 0; q < randomNumbers.length; q++){

// get the remaining possible numbers


int remainingNumbers = range-q;

// get a new random number from the remainingNumbers


int newRandSpot = (int) (Math.random()*remainingNumbers);

newRandSpot++;

// loop through all the possible numbers


for (int t = 1; t < range+1; t++){

// check to see if this number has already been taken


boolean taken = false;
for (int number : randomNumbers){
if (t==number){
taken = true;
break;
}
}

// if it hasnt been taken then remove one from the spots


if (!taken){
newRandSpot--;

// if we have gone though all the spots then set the value
if (newRandSpot==0){
randomNumbers[q] = t;
}
}
}
}
return randomNumbers;
} else {
// invalid can't have a length larger then the range of possible numbers
}
return null;
}

The method works by looping though an array that has the size of the requested length and finds the remaining

GoalKicker.com – Java® Notes for Professionals 514


length of possible numbers. It sets a random number of those possible numbers newRandSpot and finds that
number within the non taken number left. It does this by looping through the range and checking to see if that
number has already been taken.

For example if the range is 5 and the length is 3 and we have already chosen the number 2. Then we have 4
remaining numbers so we get a random number between 1 and 4 and we loop through the range(5) skipping over
any numbers that we have already used(2).

Now let's say the next number chosen between 1 & 4 is 3. On the first loop we get 1 which has not yet been taken
so we can remove 1 from 3 making it 2. Now on the second loop we get 2 which has been taken so we do nothing.
We follow this pattern until we get to 4 where once we remove 1 it becomes 0 so we set the new randomNumber to
4.

Section 87.6: Generating Random number using apache-


common lang3
We can use org.apache.commons.lang3.RandomUtils to generate random numbers using a single line.

int x = RandomUtils.nextInt(1, 1000);

The method nextInt(int startInclusive, int endExclusive) takes a range.

Apart from int, we can generate random long, double, float and bytes using this class.

RandomUtils class contains the following methods-

static byte[] nextBytes(int count) //Creates an array of random bytes.


static double nextDouble() //Returns a random double within 0 - Double.MAX_VALUE
static double nextDouble(double startInclusive, double endInclusive) //Returns a random double
within the specified range.
static float nextFloat() //Returns a random float within 0 - Float.MAX_VALUE
static float nextFloat(float startInclusive, float endInclusive) //Returns a random float within
the specified range.
static int nextInt() //Returns a random int within 0 - Integer.MAX_VALUE
static int nextInt(int startInclusive, int endExclusive) //Returns a random integer within the
specified range.
static long nextLong() //Returns a random long within 0 - Long.MAX_VALUE
static long nextLong(long startInclusive, long endExclusive) //Returns a random long within the
specified range.

GoalKicker.com – Java® Notes for Professionals 515

You might also like