Random.java revision c5722b61dd9da95dd0f05cd7f57027b88bf16dd3
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.util; 19 20 21import java.io.Serializable; 22 23/** 24 * This class provides methods that return pseudo-random values. 25 * 26 * <p>It is dangerous to seed {@code Random} with the current time because 27 * that value is more predictable to an attacker than the default seed. 28 * 29 * <p>This class is thread-safe. 30 * 31 * @see java.security.SecureRandom 32 */ 33public class Random implements Serializable { 34 35 private static final long serialVersionUID = 3905348978240129619L; 36 37 private static final long multiplier = 0x5deece66dL; 38 39 /** 40 * The boolean value indicating if the second Gaussian number is available. 41 * 42 * @serial 43 */ 44 private boolean haveNextNextGaussian; 45 46 /** 47 * @serial It is associated with the internal state of this generator. 48 */ 49 private long seed; 50 51 /** 52 * The second Gaussian generated number. 53 * 54 * @serial 55 */ 56 private double nextNextGaussian; 57 58 /** 59 * Used to generate initial seeds. 60 */ 61 private static volatile long seedBase = 0; 62 63 /** 64 * Constructs a random generator with an initial state that is 65 * unlikely to be duplicated by a subsequent instantiation. 66 */ 67 public Random() { 68 // Note: Don't use identityHashCode(this) since that causes the monitor to 69 // get inflated when we synchronize. 70 setSeed(System.nanoTime() + seedBase); 71 ++seedBase; 72 } 73 74 /** 75 * Construct a random generator with the given {@code seed} as the 76 * initial state. Equivalent to {@code Random r = new Random(); r.setSeed(seed);}. 77 * 78 * <p>This constructor is mainly useful for <i>predictability</i> in tests. 79 * The default constructor is likely to provide better randomness. 80 */ 81 public Random(long seed) { 82 setSeed(seed); 83 } 84 85 /** 86 * Returns a pseudo-random uniformly distributed {@code int} value of 87 * the number of bits specified by the argument {@code bits} as 88 * described by Donald E. Knuth in <i>The Art of Computer Programming, 89 * Volume 2: Seminumerical Algorithms</i>, section 3.2.1. 90 * 91 * <p>Most applications will want to use one of this class' convenience methods instead. 92 * 93 * <p>Subclasses only need to override this method to alter the behavior 94 * of all the public methods. 95 */ 96 protected synchronized int next(int bits) { 97 seed = (seed * multiplier + 0xbL) & ((1L << 48) - 1); 98 return (int) (seed >>> (48 - bits)); 99 } 100 101 /** 102 * Returns a pseudo-random uniformly distributed {@code boolean}. 103 */ 104 public boolean nextBoolean() { 105 return next(1) != 0; 106 } 107 108 /** 109 * Fills {@code buf} with random bytes. 110 */ 111 public void nextBytes(byte[] buf) { 112 int rand = 0, count = 0, loop = 0; 113 while (count < buf.length) { 114 if (loop == 0) { 115 rand = nextInt(); 116 loop = 3; 117 } else { 118 loop--; 119 } 120 buf[count++] = (byte) rand; 121 rand >>= 8; 122 } 123 } 124 125 /** 126 * Returns a pseudo-random uniformly distributed {@code double} 127 * in the half-open range [0.0, 1.0). 128 */ 129 public double nextDouble() { 130 return ((((long) next(26) << 27) + next(27)) / (double) (1L << 53)); 131 } 132 133 /** 134 * Returns a pseudo-random uniformly distributed {@code float} 135 * in the half-open range [0.0, 1.0). 136 */ 137 public float nextFloat() { 138 return (next(24) / 16777216f); 139 } 140 141 /** 142 * Returns a pseudo-random (approximately) normally distributed 143 * {@code double} with mean 0.0 and standard deviation 1.0. 144 * This method uses the <i>polar method</i> of G. E. P. Box, M. 145 * E. Muller, and G. Marsaglia, as described by Donald E. Knuth in <i>The 146 * Art of Computer Programming, Volume 2: Seminumerical Algorithms</i>, 147 * section 3.4.1, subsection C, algorithm P. 148 */ 149 public synchronized double nextGaussian() { 150 if (haveNextNextGaussian) { 151 haveNextNextGaussian = false; 152 return nextNextGaussian; 153 } 154 155 double v1, v2, s; 156 do { 157 v1 = 2 * nextDouble() - 1; 158 v2 = 2 * nextDouble() - 1; 159 s = v1 * v1 + v2 * v2; 160 } while (s >= 1 || s == 0); 161 162 // The specification says this uses StrictMath. 163 double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s); 164 nextNextGaussian = v2 * multiplier; 165 haveNextNextGaussian = true; 166 return v1 * multiplier; 167 } 168 169 /** 170 * Returns a pseudo-random uniformly distributed {@code int}. 171 */ 172 public int nextInt() { 173 return next(32); 174 } 175 176 /** 177 * Returns a pseudo-random uniformly distributed {@code int} 178 * in the half-open range [0, n). 179 */ 180 public int nextInt(int n) { 181 if (n <= 0) { 182 throw new IllegalArgumentException("n <= 0: " + n); 183 } 184 if ((n & -n) == n) { 185 return (int) ((n * (long) next(31)) >> 31); 186 } 187 int bits, val; 188 do { 189 bits = next(31); 190 val = bits % n; 191 } while (bits - val + (n - 1) < 0); 192 return val; 193 } 194 195 /** 196 * Returns a pseudo-random uniformly distributed {@code long}. 197 */ 198 public long nextLong() { 199 return ((long) next(32) << 32) + next(32); 200 } 201 202 /** 203 * Modifies the seed using a linear congruential formula presented in <i>The 204 * Art of Computer Programming, Volume 2</i>, Section 3.2.1. 205 */ 206 public synchronized void setSeed(long seed) { 207 this.seed = (seed ^ multiplier) & ((1L << 48) - 1); 208 haveNextNextGaussian = false; 209 } 210} 211