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 * Utility library that supplements the standard {@link Random} class.
023 * 
024 * @since 3.3
025 *
026 * @version $Id: RandomUtils.java 1557434 2014-01-11 19:10:13Z britter $
027 */
028public class RandomUtils {
029
030    /**
031     * Random object used by random method. This has to be not local to the
032     * random method so as to not return the same value in the same millisecond.
033     */
034    private static final Random RANDOM = new Random();
035
036    /**
037     * <p>
038     * {@code RandomUtils} instances should NOT be constructed in standard
039     * programming. Instead, the class should be used as
040     * {@code RandomUtils.nextBytes(5);}.
041     * </p>
042     * 
043     * <p>
044     * This constructor is public to permit tools that require a JavaBean
045     * instance to operate.
046     * </p>
047     */
048    public RandomUtils() {
049        super();
050    }
051
052    /**
053     * Creates a array of the specified length filled with random bytes.
054     * 
055     * @param count
056     *            the size of the returned array
057     * @return the random byte array
058     */
059    public static byte[] nextBytes(int count) {
060        Validate.isTrue(count >= 0, "Count cannot be negative.");
061
062        byte[] result = new byte[count];
063        RANDOM.nextBytes(result);
064        return result;
065    }
066
067    /**
068     * Returns a random integer within the specified range.
069     * 
070     * @param startInclusive
071     *            the smallest value that can be returned, must be non-negative
072     * @param endExclusive
073     *            the upper bound (not included), must be non-negative
074     * @throws IllegalArgumentException
075     *             if {@code startInclusive > endInclusive}
076     * @return the random integer
077     */
078    public static int nextInt(int startInclusive, int endExclusive) {
079        Validate.isTrue(endExclusive >= startInclusive,
080                "Start value must be smaller or equal to end value.");
081        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
082
083        if (startInclusive == endExclusive) {
084            return startInclusive;
085        }
086        
087        return startInclusive + RANDOM.nextInt(endExclusive - startInclusive);
088    }
089    
090    /**
091     * Returns a random long within the specified range.
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), must be non-negative
097     * @throws IllegalArgumentException
098     *             if {@code startInclusive > endInclusive}
099     * @return the random long
100     */
101    public static long nextLong(long startInclusive, long 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 (long) nextDouble(startInclusive, endExclusive);
111    }    
112    
113    
114    /**
115     * Returns a random double within the specified range.
116     * 
117     * @param startInclusive
118     *            the smallest value that can be returned, must be non-negative
119     * @param endInclusive
120     *            the upper bound (included), must be non-negative
121     * @throws IllegalArgumentException
122     *             if {@code startInclusive > endInclusive}
123     * @return the random double
124     */
125    public static double nextDouble(double startInclusive, double endInclusive) {
126        Validate.isTrue(endInclusive >= startInclusive,
127                "Start value must be smaller or equal to end value.");
128        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
129        
130        if (startInclusive == endInclusive) {
131            return startInclusive;
132        }
133        
134        return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextDouble());
135    }
136    
137    /**
138     * Returns a random float within the specified range.
139     * 
140     * @param startInclusive
141     *            the smallest value that can be returned, must be non-negative
142     * @param endInclusive
143     *            the upper bound (included), must be non-negative
144     * @throws IllegalArgumentException
145     *             if {@code startInclusive > endInclusive}
146     * @return the random float
147     */
148    public static float nextFloat(float startInclusive, float endInclusive) {
149        Validate.isTrue(endInclusive >= startInclusive,
150                "Start value must be smaller or equal to end value.");
151        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
152        
153        if (startInclusive == endInclusive) {
154            return startInclusive;
155        }
156        
157        return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextFloat());
158    }    
159}