All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.hasor.cobble.RandomUtils Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.hasor.cobble;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Random;

import static java.math.BigDecimal.ROUND_DOWN;

/**
 * 

Utility library that supplements the standard {@link Random} class.

* *

Caveat: Instances of {@link Random} are not cryptographically secure.

* *

Provides randomness between any two numbers, For example: arbitrarily large numbers, negative numbers

* *

that may be a better choice for applications with more stringent requirements

* * @author 赵永春 ([email protected]) */ public class RandomUtils { /** * Random object used by random method. This has to be not local to the * random method so as to not return the same value in the same millisecond. */ private static final Random RANDOM = new Random(System.currentTimeMillis()); /** *

* {@code RandomUtils} instances should NOT be constructed in standard * programming. Instead, the class should be used as * {@code RandomUtils.nextBytes(5);}. *

* *

* This constructor is public to permit tools that require a JavaBean instance to operate. *

*/ public RandomUtils() { super(); } private static void isTrue(final boolean expression, final String message, final Object... values) { if (!expression) { throw new IllegalArgumentException(String.format(message, values)); } } /** *

Returns a random boolean value

* * @return the random boolean */ public static boolean nextBoolean() { return RANDOM.nextBoolean(); } /** *

Creates an array of random bytes.

* * @param count the size of the returned array * @return the random byte array * @throws IllegalArgumentException if {@code count} is negative */ public static byte[] nextBytes(final int count) { isTrue(count >= 0, "Count cannot be negative."); final byte[] result = new byte[count]; RANDOM.nextBytes(result); return result; } /** *

fill an array of random bytes.

* * @param b fill array * @throws IllegalArgumentException if {@code count} is negative */ public static void nextBytes(byte[] b) { RANDOM.nextBytes(b); } /** *

Returns a random integer within the specified range.

* * @param startInclusive the smallest value that can be returned, must be non-negative * @param endInclusive the upper bound (included) * @throws IllegalArgumentException if {@code startInclusive > endInclusive} or if {@code startInclusive} is negative * @return the random integer */ public static int nextInt(int startInclusive, int endInclusive) { return nextBigInteger(startInclusive, endInclusive).intValue(); } /** *

Returns a random int within 0 - Integer.MAX_VALUE

* * @return the random integer * @see #nextInt(int, int) */ public static int nextInt() { return nextBigInteger(0, Integer.MAX_VALUE).intValue(); } /** *

* Returns a random long within the specified range. *

* * @param startInclusive the smallest value that can be returned, must be non-negative * @param endInclusive the upper bound (included) * @throws IllegalArgumentException if {@code startInclusive > endInclusive} or if {@code startInclusive} is negative * @return the random long */ public static long nextLong(long startInclusive, long endInclusive) { return nextBigInteger(startInclusive, endInclusive).longValue(); } /** *

Returns a random long within 0 - Long.MAX_VALUE

* * @return the random long * @see #nextLong(long, long) */ public static long nextLong() { return nextBigInteger(0, Long.MAX_VALUE).longValue(); } /** *

* Returns a random BigInteger within the specified range. *

* * @param startInclusive the smallest value that can be returned, support negative * @param endInclusive the upper bound (included) * @throws IllegalArgumentException if {@code startInclusive > endInclusive} or if {@code startInclusive} is negative * @return the random long */ public static BigInteger nextBigInteger(Number startInclusive, Number endInclusive) { BigInteger minBig = (startInclusive instanceof BigInteger) ? (BigInteger) startInclusive : (startInclusive instanceof BigDecimal) ? ((BigDecimal) startInclusive).toBigInteger() : (BigInteger.valueOf(startInclusive.longValue())); BigInteger maxBig = (endInclusive instanceof BigInteger) ? (BigInteger) endInclusive : (endInclusive instanceof BigDecimal) ? ((BigDecimal) endInclusive).toBigInteger() : (BigInteger.valueOf(endInclusive.longValue())); int signum = minBig.signum() == maxBig.signum() ? minBig.signum() : 1; BigInteger offset; BigInteger bigRange; if (signum == -1 || minBig.equals(BigInteger.ZERO)) { offset = minBig.abs(); bigRange = minBig.abs().add(maxBig.abs()); } else { offset = minBig.negate(); bigRange = maxBig.subtract(minBig); } StringBuilder result = new StringBuilder(); boolean inFree = false; char[] bitChars = bigRange.toString(2).toCharArray(); for (char rangeChar : bitChars) { if (inFree) { result.append(nextBoolean() ? 1 : 0); } else { boolean oriBit = rangeChar == '1'; boolean newBit = nextBoolean(); inFree = oriBit != newBit && oriBit; if (inFree) { result.append(0); } else { result.append(oriBit ? 1 : 0); } } } BigInteger after = new BigInteger(result.toString(), 2); if (signum == -1) { return after.negate().subtract(offset); } else { return after.subtract(offset); } } /** *

* Returns a random double within the specified range. *

* * @param startInclusive the smallest value that can be returned, support negative * @param endInclusive the upper bound (included) * @throws IllegalArgumentException if {@code startInclusive > endInclusive} or if {@code startInclusive} is negative * @return the random double */ public static double nextDouble(final double startInclusive, final double endInclusive) { isTrue(endInclusive >= startInclusive, "Start value must be smaller or equal to end value."); isTrue(startInclusive >= 0, "Both range values support negative."); if (startInclusive == endInclusive) { return startInclusive; } return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextDouble()); } /** *

Returns a random double within 0 - Double.MAX_VALUE

* * @return the random double * @see #nextDouble(double, double) * @since 3.5 */ public static double nextDouble() { return nextDouble(0, Double.MAX_VALUE); } /** *

* Returns a random float within the specified range. *

* * @param startInclusive the smallest value that can be returned, support negative * @param endInclusive the upper bound (included) * @throws IllegalArgumentException if {@code startInclusive > endInclusive} or if {@code startInclusive} is negative * @return the random float */ public static float nextFloat(final float startInclusive, final float endInclusive) { isTrue(endInclusive >= startInclusive, "Start value must be smaller or equal to end value."); isTrue(startInclusive >= 0, "Both range values support negative."); if (startInclusive == endInclusive) { return startInclusive; } return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextFloat()); } /** *

Returns a random float within 0 - Float.MAX_VALUE

* * @return the random float * @see #nextFloat() */ public static float nextFloat() { return nextFloat(0, Float.MAX_VALUE); } /** *

* Returns a random BigDecimal within the specified range. *

* * @param startInclusive the smallest value that can be returned, support negative * @param endInclusive the upper bound (included) * @throws IllegalArgumentException if {@code startInclusive > endInclusive} or if {@code startInclusive} is negative * @return the random BigDecimal */ public static BigDecimal nextDecimal(Number startInclusive, Number endInclusive, Integer scale) { BigDecimal minBig = (startInclusive instanceof BigDecimal) ? (BigDecimal) startInclusive : (startInclusive instanceof BigInteger) ? new BigDecimal((BigInteger) startInclusive) : (BigDecimal.valueOf(startInclusive.doubleValue())); BigDecimal maxBig = (endInclusive instanceof BigDecimal) ? (BigDecimal) endInclusive : (endInclusive instanceof BigInteger) ? new BigDecimal((BigInteger) endInclusive) : (BigDecimal.valueOf(endInclusive.doubleValue())); if (scale == null) { BigDecimal[] minParts = minBig.divideAndRemainder(BigDecimal.ONE); BigDecimal[] maxParts = maxBig.divideAndRemainder(BigDecimal.ONE); scale = Math.max(minParts[1].scale(), maxParts[1].scale()); } BigDecimal result; if (scale == 0) { result = new BigDecimal(nextBigInteger(minBig, maxBig)); } else { BigDecimal scaleMul = new BigDecimal("1" + StringUtils.repeat("0", scale)); BigDecimal scaleMin = minBig.multiply(scaleMul); BigDecimal scaleMax = maxBig.multiply(scaleMul); result = new BigDecimal(nextBigInteger(scaleMin, scaleMax)).divide(scaleMul); } return result.setScale(scale, ROUND_DOWN); } /** *

* Returns a random BigDecimal within the specified range. *

* * @param precision precision of random number * @param scale scale of random number * @return the random BigDecimal */ public static BigDecimal nextDecimal(Integer precision, Integer scale) { if (precision == null && scale == null) { return BigDecimal.valueOf(nextDouble()); } if (precision == null) { precision = scale; } if (scale == null) { scale = 0; } BigDecimal randomDecimal = new BigDecimal(nextBigInteger(0, new BigInteger(StringUtils.repeat("9", precision)))); BigDecimal divNum = new BigDecimal("1" + StringUtils.repeat("0", scale)); randomDecimal = randomDecimal.divide(divNum, scale, ROUND_DOWN).stripTrailingZeros(); return nextBoolean() ? randomDecimal : randomDecimal.negate(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy