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

com.cedarsoftware.util.MathUtilities Maven / Gradle / Ivy

The newest version!
package com.cedarsoftware.util;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;

import static java.util.Collections.swap;

/**
 * Useful Math utilities
 *
 * @author John DeRegnaucourt ([email protected])
 *         
* Copyright (c) Cedar Software LLC *

* Licensed 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 *

* License *

* 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. */ public final class MathUtilities { public static final BigInteger BIG_INT_LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE); public static final BigInteger BIG_INT_LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE); public static final BigDecimal BIG_DEC_DOUBLE_MIN = BigDecimal.valueOf(-Double.MAX_VALUE); public static final BigDecimal BIG_DEC_DOUBLE_MAX = BigDecimal.valueOf(Double.MAX_VALUE); private MathUtilities() { super(); } /** * Calculate the minimum value from an array of values. * * @param values Array of values. * @return minimum value of the provided set. */ public static long minimum(long... values) { final int len = values.length; long current = values[0]; for (int i=1; i < len; i++) { current = Math.min(values[i], current); } return current; } /** * Calculate the minimum value from an array of values. * * @param values Array of values. * @return minimum value of the provided set. */ public static long maximum(long... values) { final int len = values.length; long current = values[0]; for (int i=1; i < len; i++) { current = Math.max(values[i], current); } return current; } /** * Calculate the minimum value from an array of values. * * @param values Array of values. * @return minimum value of the provided set. */ public static double minimum(double... values) { final int len =values.length; double current = values[0]; for (int i=1; i < len; i++) { current = Math.min(values[i], current); } return current; } /** * Calculate the minimum value from an array of values. * * @param values Array of values. * @return minimum value of the provided set. */ public static double maximum(double... values) { final int len = values.length; double current = values[0]; for (int i=1; i < len; i++) { current = Math.max(values[i], current); } return current; } /** * Calculate the minimum value from an array of values. * * @param values Array of values. * @return minimum value of the provided set. */ public static BigInteger minimum(BigInteger... values) { final int len = values.length; if (len == 1) { if (values[0] == null) { throw new IllegalArgumentException("Cannot passed null BigInteger entry to minimum()"); } return values[0]; } BigInteger current = values[0]; for (int i=1; i < len; i++) { if (values[i] == null) { throw new IllegalArgumentException("Cannot passed null BigInteger entry to minimum()"); } current = values[i].min(current); } return current; } /** * Calculate the minimum value from an array of values. * * @param values Array of values. * @return minimum value of the provided set. */ public static BigInteger maximum(BigInteger... values) { final int len = values.length; if (len == 1) { if (values[0] == null) { throw new IllegalArgumentException("Cannot passed null BigInteger entry to maximum()"); } return values[0]; } BigInteger current = values[0]; for (int i=1; i < len; i++) { if (values[i] == null) { throw new IllegalArgumentException("Cannot passed null BigInteger entry to maximum()"); } current = values[i].max(current); } return current; } /** * Calculate the minimum value from an array of values. * * @param values Array of values. * @return minimum value of the provided set. */ public static BigDecimal minimum(BigDecimal... values) { final int len = values.length; if (len == 1) { if (values[0] == null) { throw new IllegalArgumentException("Cannot passed null BigDecimal entry to minimum()"); } return values[0]; } BigDecimal current = values[0]; for (int i=1; i < len; i++) { if (values[i] == null) { throw new IllegalArgumentException("Cannot passed null BigDecimal entry to minimum()"); } current = values[i].min(current); } return current; } /** * Calculate the maximum value from an array of values. * * @param values Array of values. * @return maximum value of the provided set. */ public static BigDecimal maximum(BigDecimal... values) { final int len = values.length; if (len == 1) { if (values[0] == null) { throw new IllegalArgumentException("Cannot pass null BigDecimal entry to maximum()"); } return values[0]; } BigDecimal current = values[0]; for (int i=1; i < len; i++) { if (values[i] == null) { throw new IllegalArgumentException("Cannot pass null BigDecimal entry to maximum()"); } current = values[i].max(current); } return current; } /** * Parse the passed in String as a numeric value and return the minimal data type between Long, Double, * BigDecimal, or BigInteger. Useful for processing values from JSON files. * @param numStr String to parse. * @return Long, BigInteger, Double, or BigDecimal depending on the value. If the value is and integer and * between the range of Long min/max, a Long is returned. If the value is an integer and outside this range, a * BigInteger is returned. If the value is a decimal but within the confines of a Double, then a Double is * returned, otherwise a BigDecimal is returned. */ public static Number parseToMinimalNumericType(String numStr) { // Handle and preserve negative signs correctly while removing leading zeros boolean isNegative = numStr.startsWith("-"); if (isNegative || numStr.startsWith("+")) { char sign = numStr.charAt(0); numStr = sign + numStr.substring(1).replaceFirst("^0+", ""); } else { numStr = numStr.replaceFirst("^0+", ""); } boolean hasDecimalPoint = false; boolean hasExponent = false; int mantissaSize = 0; StringBuilder exponentValue = new StringBuilder(); int len = numStr.length(); for (int i = 0; i < len; i++) { char c = numStr.charAt(i); if (c == '.') { hasDecimalPoint = true; } else if (c == 'e' || c == 'E') { hasExponent = true; } else if (c >= '0' && c <= '9') { if (!hasExponent) { mantissaSize++; // Count digits in the mantissa only } else { exponentValue.append(c); } } } if (hasDecimalPoint || hasExponent) { if (mantissaSize < 17 && (exponentValue.length() == 0 || Math.abs(Integer.parseInt(exponentValue.toString())) < 308)) { return Double.parseDouble(numStr); } else { return new BigDecimal(numStr); } } else { if (numStr.length() < 19) { return Long.parseLong(numStr); } BigInteger bigInt = new BigInteger(numStr); if (bigInt.compareTo(BIG_INT_LONG_MIN) >= 0 && bigInt.compareTo(BIG_INT_LONG_MAX) <= 0) { return bigInt.longValue(); // Correctly convert BigInteger back to Long if within range } else { return bigInt; } } } /** * Utility method for generating the "next" permutation. * @param list List of integers, longs, etc. Typically, something like [1, 2, 3, 4] and it * will generate the next permutation [1, 2, 4, 3]. It will override the passed in * list. This way, each call to nextPermutation(list) works, until it returns false, * much like an Iterator. */ static > boolean nextPermutation(List list) { int k = list.size() - 2; while (k >= 0 && list.get(k).compareTo(list.get(k + 1)) >= 0) { k--; } if (k < 0) { return false; // No more permutations } int l = list.size() - 1; while (list.get(k).compareTo(list.get(l)) >= 0) { l--; } swap(list, k, l); for (int i = k + 1, j = list.size() - 1; i < j; i++, j--) { swap(list, i, j); } return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy