// CS 1538 Fall 2009 // This handout verifies that the Random number generator that is standard // in Java meets the theoretical guidelines of a mixed linear congruential // generator with period m as stated in the textbook. Note that it does NOT // actually test to see if the values generated are uniform and independent. import java.util.*; import java.math.*; public class TestRandom { public static void main(String [] args) { long a = 0x5DEECE66DL; long c = 0xBL; long mask = (1L << 48) - 1; // We will verify that these values fit with the first form // of the linear congruential generator from p. 280 of the text // (the mixed generator) // First we test to see if a = 1 + 4k for some k. If this is // true, then a-1 = 4k for some k and thus (a-1)%4 = 0; long aMinus1 = a - 1; if (aMinus1 % 4 == 0) { long quot = aMinus1 / 4; System.out.println(a + " = 1 + 4(" + quot + ")"); } else System.out.println("Not valid 1"); // Now we want to make sure the c and m are relatively prime // The way the mask is defined is that it is 2^48 - 1, which will // give 1s in the rightmost 48 bits of the number and zeros in the // leftmost bits. This in effect produces an m of 2^48, so that is // what we will test. To be relatively prime, two numbers must have // a greatest common divisor of 0. A predefined gcd function is not // defined in the Java Math class, but it is defined in the BigInteger // class. BigInteger bigC = new BigInteger(String.valueOf(c)); BigInteger bigM = new BigInteger(String.valueOf(mask+1)); BigInteger gcd = bigC.gcd(bigM); if (gcd.equals(new BigInteger("1"))) System.out.println(c + " and " + (mask+1) + " are relatively prime"); else System.out.println("Not valid 2"); // The code below will test the period. Note that if the theory is // correct, the period will be m = 2^48 which will clearly take a VERY // long time to circle through. However, since we are limiting the values // to the range of 32-bit integers, we could get a duplicate // earlier (but a duplicate here does not mean that the period has // completed, since we are throwing away some of the bits). long count = 0; Random R = new Random(); int i = R.nextInt(); count = 1; int first = i; i = R.nextInt(); while (i != first && count <= (1L << 32)) { count++; if (count % 20000000 == 0) System.out.println(count + " tried "); i = R.nextInt(); } if (i == first) System.out.println("Duplicate of first found after " + count + " numbers"); else System.out.println("No duplicates found"); } }