    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.lang3;
    018
    019import java.util.Random;
    020
    021/**
    022 * <p>Utility library that supplements the standard {@link Random} class.</p>
    023 *
    024 * <p>Caveat: Instances of {@link Random} are not cryptographically secure.</p>
    025 *
    026 * <p>Please note that the Apache Commons project provides a component
    027 * dedicated to pseudo-random number generation, namely
    028 * <a href="https://commons.apache.org/rng">Commons RNG</a>, that may be
    029 * a better choice for applications with more stringent requirements
    030 * (performance and/or correctness).</p>
    031 *
    032 * @since 3.3
    033 */
    034public class RandomUtils {
    035
    036    /**
    037     * Random object used by random method. This has to be not local to the
    038     * random method so as to not return the same value in the same millisecond.
    039     */
    040    private static final Random RANDOM = new Random();
    041
    042    /**
    043     * <p>
    044     * {@code RandomUtils} instances should NOT be constructed in standard
    045     * programming. Instead, the class should be used as
    046     * {@code RandomUtils.nextBytes(5);}.
    047     * </p>
    048     *
    049     * <p>
    050     * This constructor is public to permit tools that require a JavaBean
    051     * instance to operate.
    052     * </p>
    053     */
    054    public RandomUtils() {
    055    }
    056
    057    /**
    058     * <p>
    059     * Returns a random boolean value
    060     * </p>
    061     *
    062     * @return the random boolean
    063     * @since 3.5
    064     */
    065    public static boolean nextBoolean() {
    066        return RANDOM.nextBoolean();
    067    }
    068
    069    /**
    070     * <p>
    071     * Creates an array of random bytes.
    072     * </p>
    073     *
    074     * @param count
    075     *            the size of the returned array
    076     * @return the random byte array
    077     * @throws IllegalArgumentException if {@code count} is negative
    078     */
    079    public static byte[] nextBytes(final int count) {
    080        Validate.isTrue(count >= 0, "Count cannot be negative.");
    081
    082        final byte[] result = new byte[count];
    083        RANDOM.nextBytes(result);
    084        return result;
    085    }
    086
    087    /**
    088     * <p>
    089     * Returns a random integer within the specified range.
    090     * </p>
    091     *
    092     * @param startInclusive
    093     *            the smallest value that can be returned, must be non-negative
    094     * @param endExclusive
    095     *            the upper bound (not included)
    096     * @throws IllegalArgumentException
    097     *             if {@code startInclusive > endExclusive} or if
    098     *             {@code startInclusive} is negative
    099     * @return the random integer
    100     */
    101    public static int nextInt(final int startInclusive, final int endExclusive) {
    102        Validate.isTrue(endExclusive >= startInclusive,
    103                "Start value must be smaller or equal to end value.");
    104        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
    105
    106        if (startInclusive == endExclusive) {
    107            return startInclusive;
    108        }
    109
    110        return startInclusive + RANDOM.nextInt(endExclusive - startInclusive);
    111    }
    112
    113    /**
    114     * <p> Returns a random int within 0 - Integer.MAX_VALUE </p>
    115     *
    116     * @return the random integer
    117     * @see #nextInt(int, int)
    118     * @since 3.5
    119     */
    120    public static int nextInt() {
    121        return nextInt(0, Integer.MAX_VALUE);
    122    }
    123
    124    /**
    125     * <p>
    126     * Returns a random long within the specified range.
    127     * </p>
    128     *
    129     * @param startInclusive
    130     *            the smallest value that can be returned, must be non-negative
    131     * @param endExclusive
    132     *            the upper bound (not included)
    133     * @throws IllegalArgumentException
    134     *             if {@code startInclusive > endExclusive} or if
    135     *             {@code startInclusive} is negative
    136     * @return the random long
    137     */
    138    public static long nextLong(final long startInclusive, final long endExclusive) {
    139        Validate.isTrue(endExclusive >= startInclusive,
    140                "Start value must be smaller or equal to end value.");
    141        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
    142
    143        if (startInclusive == endExclusive) {
    144            return startInclusive;
    145        }
    146
    147        return startInclusive + nextLong(endExclusive - startInclusive);
    148    }
    149
    150    /**
    151     * <p> Returns a random long within 0 - Long.MAX_VALUE </p>
    152     *
    153     * @return the random long
    154     * @see #nextLong(long, long)
    155     * @since 3.5
    156     */
    157    public static long nextLong() {
    158        return nextLong(Long.MAX_VALUE);
    159    }
    160
    161    /**
    162     * Generates a {@code long} value between 0 (inclusive) and the specified
    163     * value (exclusive).
    164     *
    165     * @param n Bound on the random number to be returned.  Must be positive.
    166     * @return a random {@code long} value between 0 (inclusive) and {@code n}
    167     * (exclusive).
    168     */
    169    private static long nextLong(final long n) {
    170        // Extracted from o.a.c.rng.core.BaseProvider.nextLong(long)
    171        long bits;
    172        long val;
    173        do {
    174            bits = RANDOM.nextLong() >>> 1;
    175            val  = bits % n;
    176        } while (bits - val + (n - 1) < 0);
    177
    178        return val;
    179    }
    180
    181    /**
    182     * <p>
    183     * Returns a random double within the specified range.
    184     * </p>
    185     *
    186     * @param startInclusive
    187     *            the smallest value that can be returned, must be non-negative
    188     * @param endExclusive
    189     *            the upper bound (not included)
    190     * @throws IllegalArgumentException
    191     *             if {@code startInclusive > endExclusive} or if
    192     *             {@code startInclusive} is negative
    193     * @return the random double
    194     */
    195    public static double nextDouble(final double startInclusive, final double endExclusive) {
    196        Validate.isTrue(endExclusive >= startInclusive,
    197                "Start value must be smaller or equal to end value.");
    198        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
    199
    200        if (startInclusive == endExclusive) {
    201            return startInclusive;
    202        }
    203
    204        return startInclusive + ((endExclusive - startInclusive) * RANDOM.nextDouble());
    205    }
    206
    207    /**
    208     * <p> Returns a random double within 0 - Double.MAX_VALUE </p>
    209     *
    210     * @return the random double
    211     * @see #nextDouble(double, double)
    212     * @since 3.5
    213     */
    214    public static double nextDouble() {
    215        return nextDouble(0, Double.MAX_VALUE);
    216    }
    217
    218    /**
    219     * <p>
    220     * Returns a random float within the specified range.
    221     * </p>
    222     *
    223     * @param startInclusive
    224     *            the smallest value that can be returned, must be non-negative
    225     * @param endExclusive
    226     *            the upper bound (not included)
    227     * @throws IllegalArgumentException
    228     *             if {@code startInclusive > endExclusive} or if
    229     *             {@code startInclusive} is negative
    230     * @return the random float
    231     */
    232    public static float nextFloat(final float startInclusive, final float endExclusive) {
    233        Validate.isTrue(endExclusive >= startInclusive,
    234                "Start value must be smaller or equal to end value.");
    235        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
    236
    237        if (startInclusive == endExclusive) {
    238            return startInclusive;
    239        }
    240
    241        return startInclusive + ((endExclusive - startInclusive) * RANDOM.nextFloat());
    242    }
    243
    244    /**
    245     * <p> Returns a random float within 0 - Float.MAX_VALUE </p>
    246     *
    247     * @return the random float
    248     * @see #nextFloat(float, float)
    249     * @since 3.5
    250     */
    251    public static float nextFloat() {
    252        return nextFloat(0, Float.MAX_VALUE);
    253    }
    254}