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        super();
056    }
057
058    /**
059     * <p>
060     * Returns a random boolean value
061     * </p>
062     *
063     * @return the random boolean
064     * @since 3.5
065     */
066    public static boolean nextBoolean() {
067        return RANDOM.nextBoolean();
068    }
069
070    /**
071     * <p>
072     * Creates an array of random bytes.
073     * </p>
074     *
075     * @param count
076     *            the size of the returned array
077     * @return the random byte array
078     * @throws IllegalArgumentException if {@code count} is negative
079     */
080    public static byte[] nextBytes(final int count) {
081        Validate.isTrue(count >= 0, "Count cannot be negative.");
082
083        final byte[] result = new byte[count];
084        RANDOM.nextBytes(result);
085        return result;
086    }
087
088    /**
089     * <p>
090     * Returns a random integer within the specified range.
091     * </p>
092     *
093     * @param startInclusive
094     *            the smallest value that can be returned, must be non-negative
095     * @param endExclusive
096     *            the upper bound (not included)
097     * @throws IllegalArgumentException
098     *             if {@code startInclusive > endExclusive} or if
099     *             {@code startInclusive} is negative
100     * @return the random integer
101     */
102    public static int nextInt(final int startInclusive, final int endExclusive) {
103        Validate.isTrue(endExclusive >= startInclusive,
104                "Start value must be smaller or equal to end value.");
105        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
106
107        if (startInclusive == endExclusive) {
108            return startInclusive;
109        }
110
111        return startInclusive + RANDOM.nextInt(endExclusive - startInclusive);
112    }
113
114    /**
115     * <p> Returns a random int within 0 - Integer.MAX_VALUE </p>
116     *
117     * @return the random integer
118     * @see #nextInt(int, int)
119     * @since 3.5
120     */
121    public static int nextInt() {
122        return nextInt(0, Integer.MAX_VALUE);
123    }
124
125    /**
126     * <p>
127     * Returns a random long within the specified range.
128     * </p>
129     *
130     * @param startInclusive
131     *            the smallest value that can be returned, must be non-negative
132     * @param endExclusive
133     *            the upper bound (not included)
134     * @throws IllegalArgumentException
135     *             if {@code startInclusive > endExclusive} or if
136     *             {@code startInclusive} is negative
137     * @return the random long
138     */
139    public static long nextLong(final long startInclusive, final long endExclusive) {
140        Validate.isTrue(endExclusive >= startInclusive,
141                "Start value must be smaller or equal to end value.");
142        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
143
144        if (startInclusive == endExclusive) {
145            return startInclusive;
146        }
147
148        return (long) nextDouble(startInclusive, endExclusive);
149    }
150
151    /**
152     * <p> Returns a random long within 0 - Long.MAX_VALUE </p>
153     *
154     * @return the random long
155     * @see #nextLong(long, long)
156     * @since 3.5
157     */
158    public static long nextLong() {
159        return nextLong(0, Long.MAX_VALUE);
160    }
161
162    /**
163     * <p>
164     * Returns a random double within the specified range.
165     * </p>
166     *
167     * @param startInclusive
168     *            the smallest value that can be returned, must be non-negative
169     * @param endExclusive
170     *            the upper bound (not included)
171     * @throws IllegalArgumentException
172     *             if {@code startInclusive > endExclusive} or if
173     *             {@code startInclusive} is negative
174     * @return the random double
175     */
176    public static double nextDouble(final double startInclusive, final double endExclusive) {
177        Validate.isTrue(endExclusive >= startInclusive,
178                "Start value must be smaller or equal to end value.");
179        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
180
181        if (startInclusive == endExclusive) {
182            return startInclusive;
183        }
184
185        return startInclusive + ((endExclusive - startInclusive) * RANDOM.nextDouble());
186    }
187
188    /**
189     * <p> Returns a random double within 0 - Double.MAX_VALUE </p>
190     *
191     * @return the random double
192     * @see #nextDouble(double, double)
193     * @since 3.5
194     */
195    public static double nextDouble() {
196        return nextDouble(0, Double.MAX_VALUE);
197    }
198
199    /**
200     * <p>
201     * Returns a random float within the specified range.
202     * </p>
203     *
204     * @param startInclusive
205     *            the smallest value that can be returned, must be non-negative
206     * @param endExclusive
207     *            the upper bound (not included)
208     * @throws IllegalArgumentException
209     *             if {@code startInclusive > endExclusive} or if
210     *             {@code startInclusive} is negative
211     * @return the random float
212     */
213    public static float nextFloat(final float startInclusive, final float endExclusive) {
214        Validate.isTrue(endExclusive >= startInclusive,
215                "Start value must be smaller or equal to end value.");
216        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
217
218        if (startInclusive == endExclusive) {
219            return startInclusive;
220        }
221
222        return startInclusive + ((endExclusive - startInclusive) * RANDOM.nextFloat());
223    }
224
225    /**
226     * <p> Returns a random float within 0 - Float.MAX_VALUE </p>
227     *
228     * @return the random float
229     * @see #nextFloat(float, float)
230     * @since 3.5
231     */
232    public static float nextFloat() {
233        return nextFloat(0, Float.MAX_VALUE);
234    }
235}