Home | History | Annotate | Download | only in util
      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 
     18 package java.util;
     19 
     20 
     21 import 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  */
     33 public 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      * Constructs a random generator with an initial state that is
     60      * unlikely to be duplicated by a subsequent instantiation.
     61      *
     62      * <p>The initial state (that is, the seed) is <i>partially</i> based
     63      * on the current time of day in milliseconds.
     64      */
     65     public Random() {
     66         // Note: Using identityHashCode() to be hermetic wrt subclasses.
     67         setSeed(System.currentTimeMillis() + System.identityHashCode(this));
     68     }
     69 
     70     /**
     71      * Construct a random generator with the given {@code seed} as the
     72      * initial state. Equivalent to {@code Random r = new Random(); r.setSeed(seed);}.
     73      *
     74      * <p>This constructor is mainly useful for <i>predictability</i> in tests.
     75      * The default constructor is likely to provide better randomness.
     76      */
     77     public Random(long seed) {
     78         setSeed(seed);
     79     }
     80 
     81     /**
     82      * Returns a pseudo-random uniformly distributed {@code int} value of
     83      * the number of bits specified by the argument {@code bits} as
     84      * described by Donald E. Knuth in <i>The Art of Computer Programming,
     85      * Volume 2: Seminumerical Algorithms</i>, section 3.2.1.
     86      *
     87      * <p>Most applications will want to use one of this class' convenience methods instead.
     88      */
     89     protected synchronized int next(int bits) {
     90         seed = (seed * multiplier + 0xbL) & ((1L << 48) - 1);
     91         return (int) (seed >>> (48 - bits));
     92     }
     93 
     94     /**
     95      * Returns a pseudo-random uniformly distributed {@code boolean}.
     96      */
     97     public boolean nextBoolean() {
     98         return next(1) != 0;
     99     }
    100 
    101     /**
    102      * Fills {@code buf} with random bytes.
    103      */
    104     public void nextBytes(byte[] buf) {
    105         int rand = 0, count = 0, loop = 0;
    106         while (count < buf.length) {
    107             if (loop == 0) {
    108                 rand = nextInt();
    109                 loop = 3;
    110             } else {
    111                 loop--;
    112             }
    113             buf[count++] = (byte) rand;
    114             rand >>= 8;
    115         }
    116     }
    117 
    118     /**
    119      * Returns a pseudo-random uniformly distributed {@code double}
    120      * in the half-open range [0.0, 1.0).
    121      */
    122     public double nextDouble() {
    123         return ((((long) next(26) << 27) + next(27)) / (double) (1L << 53));
    124     }
    125 
    126     /**
    127      * Returns a pseudo-random uniformly distributed {@code float}
    128      * in the half-open range [0.0, 1.0).
    129      */
    130     public float nextFloat() {
    131         return (next(24) / 16777216f);
    132     }
    133 
    134     /**
    135      * Returns a pseudo-random (approximately) normally distributed
    136      * {@code double} with mean 0.0 and standard deviation 1.0.
    137      * This method uses the <i>polar method</i> of G. E. P. Box, M.
    138      * E. Muller, and G. Marsaglia, as described by Donald E. Knuth in <i>The
    139      * Art of Computer Programming, Volume 2: Seminumerical Algorithms</i>,
    140      * section 3.4.1, subsection C, algorithm P.
    141      */
    142     public synchronized double nextGaussian() {
    143         if (haveNextNextGaussian) { // if X1 has been returned, return the
    144                                     // second Gaussian
    145             haveNextNextGaussian = false;
    146             return nextNextGaussian;
    147         }
    148 
    149         double v1, v2, s;
    150         do {
    151             v1 = 2 * nextDouble() - 1; // Generates two independent random
    152                                         // variables U1, U2
    153             v2 = 2 * nextDouble() - 1;
    154             s = v1 * v1 + v2 * v2;
    155         } while (s >= 1);
    156         double norm = Math.sqrt(-2 * Math.log(s) / s);
    157         nextNextGaussian = v2 * norm; // should that not be norm instead
    158                                         // of multiplier ?
    159         haveNextNextGaussian = true;
    160         return v1 * norm; // should that not be norm instead of multiplier
    161                             // ?
    162     }
    163 
    164     /**
    165      * Returns a pseudo-random uniformly distributed {@code int}.
    166      */
    167     public int nextInt() {
    168         return next(32);
    169     }
    170 
    171     /**
    172      * Returns a pseudo-random uniformly distributed {@code int}
    173      * in the half-open range [0, n).
    174      */
    175     public int nextInt(int n) {
    176         if (n > 0) {
    177             if ((n & -n) == n) {
    178                 return (int) ((n * (long) next(31)) >> 31);
    179             }
    180             int bits, val;
    181             do {
    182                 bits = next(31);
    183                 val = bits % n;
    184             } while (bits - val + (n - 1) < 0);
    185             return val;
    186         }
    187         throw new IllegalArgumentException();
    188     }
    189 
    190     /**
    191      * Returns a pseudo-random uniformly distributed {@code long}.
    192      */
    193     public long nextLong() {
    194         return ((long) next(32) << 32) + next(32);
    195     }
    196 
    197     /**
    198      * Modifies the seed using a linear congruential formula presented in <i>The
    199      * Art of Computer Programming, Volume 2</i>, Section 3.2.1.
    200      */
    201     public synchronized void setSeed(long seed) {
    202         this.seed = (seed ^ multiplier) & ((1L << 48) - 1);
    203         haveNextNextGaussian = false;
    204     }
    205 }
    206