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 * @since 3.3
025 */
026public class RandomUtils {
027
028    /**
029     * Random object used by random method. This has to be not local to the
030     * random method so as to not return the same value in the same millisecond.
031     */
032    private static final Random RANDOM = new Random();
033
034    /**
035     * <p>
036     * {@code RandomUtils} instances should NOT be constructed in standard
037     * programming. Instead, the class should be used as
038     * {@code RandomUtils.nextBytes(5);}.
039     * </p>
040     * 
041     * <p>
042     * This constructor is public to permit tools that require a JavaBean
043     * instance to operate.
044     * </p>
045     */
046    public RandomUtils() {
047        super();
048    }
049
050    /**
051     * <p>
052     * Returns a random boolean value
053     * </p>
054     *
055     * @return the random boolean
056     * @since 3.5
057     */
058    public static boolean nextBoolean() {
059        return RANDOM.nextBoolean();
060    }
061    
062    /**
063     * <p>
064     * Creates an array of random bytes.
065     * </p>
066     * 
067     * @param count
068     *            the size of the returned array
069     * @return the random byte array
070     * @throws IllegalArgumentException if {@code count} is negative
071     */
072    public static byte[] nextBytes(final int count) {
073        Validate.isTrue(count >= 0, "Count cannot be negative.");
074
075        final byte[] result = new byte[count];
076        RANDOM.nextBytes(result);
077        return result;
078    }
079
080    /**
081     * <p>
082     * Returns a random integer within the specified range.
083     * </p>
084     * 
085     * @param startInclusive
086     *            the smallest value that can be returned, must be non-negative
087     * @param endExclusive
088     *            the upper bound (not included)
089     * @throws IllegalArgumentException
090     *             if {@code startInclusive > endExclusive} or if
091     *             {@code startInclusive} is negative
092     * @return the random integer
093     */
094    public static int nextInt(final int startInclusive, final int endExclusive) {
095        Validate.isTrue(endExclusive >= startInclusive,
096                "Start value must be smaller or equal to end value.");
097        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
098
099        if (startInclusive == endExclusive) {
100            return startInclusive;
101        }
102        
103        return startInclusive + RANDOM.nextInt(endExclusive - startInclusive);
104    }
105
106    /**
107     * <p> Returns a random int within 0 - Integer.MAX_VALUE </p>
108     *
109     * @return the random integer
110     * @see #nextInt(int, int)
111     * @since 3.5
112     */
113    public static int nextInt() {
114        return nextInt(0, Integer.MAX_VALUE);
115    }
116    
117    /**
118     * <p>
119     * Returns a random long within the specified range.
120     * </p>
121     * 
122     * @param startInclusive
123     *            the smallest value that can be returned, must be non-negative
124     * @param endExclusive
125     *            the upper bound (not included)
126     * @throws IllegalArgumentException
127     *             if {@code startInclusive > endExclusive} or if
128     *             {@code startInclusive} is negative
129     * @return the random long
130     */
131    public static long nextLong(final long startInclusive, final long endExclusive) {
132        Validate.isTrue(endExclusive >= startInclusive,
133                "Start value must be smaller or equal to end value.");
134        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
135
136        if (startInclusive == endExclusive) {
137            return startInclusive;
138        }
139
140        return (long) nextDouble(startInclusive, endExclusive);
141    }
142
143    /**
144     * <p> Returns a random long within 0 - Long.MAX_VALUE </p>
145     *
146     * @return the random long
147     * @see #nextLong(long, long)
148     * @since 3.5
149     */
150    public static long nextLong() {
151        return nextLong(0, Long.MAX_VALUE);
152    }
153    
154    /**
155     * <p> 
156     * Returns a random double within the specified range.
157     * </p>
158     * 
159     * @param startInclusive
160     *            the smallest value that can be returned, must be non-negative
161     * @param endInclusive
162     *            the upper bound (included)
163     * @throws IllegalArgumentException
164     *             if {@code startInclusive > endInclusive} or if
165     *             {@code startInclusive} is negative
166     * @return the random double
167     */
168    public static double nextDouble(final double startInclusive, final double endInclusive) {
169        Validate.isTrue(endInclusive >= startInclusive,
170                "Start value must be smaller or equal to end value.");
171        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
172
173        if (startInclusive == endInclusive) {
174            return startInclusive;
175        }
176        
177        return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextDouble());
178    }
179
180    /**
181     * <p> Returns a random double within 0 - Double.MAX_VALUE </p>
182     *
183     * @return the random double
184     * @see #nextDouble(double, double)
185     * @since 3.5
186     */
187    public static double nextDouble() {
188        return nextDouble(0, Double.MAX_VALUE);
189    }
190
191    /**
192     * <p>
193     * Returns a random float within the specified range.
194     * </p>
195     * 
196     * @param startInclusive
197     *            the smallest value that can be returned, must be non-negative
198     * @param endInclusive
199     *            the upper bound (included)
200     * @throws IllegalArgumentException
201     *             if {@code startInclusive > endInclusive} or if
202     *             {@code startInclusive} is negative
203     * @return the random float
204     */
205    public static float nextFloat(final float startInclusive, final float endInclusive) {
206        Validate.isTrue(endInclusive >= startInclusive,
207                "Start value must be smaller or equal to end value.");
208        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
209        
210        if (startInclusive == endInclusive) {
211            return startInclusive;
212        }
213        
214        return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextFloat());
215    }
216
217    /**
218     * <p> Returns a random float within 0 - Float.MAX_VALUE </p>
219     *
220     * @return the random float
221     * @see #nextFloat()
222     * @since 3.5
223     */
224    public static float nextFloat() {
225        return nextFloat(0, Float.MAX_VALUE);
226    }
227}