/* * Copyright 2013 Martin Smock <smock.martin@gmail.com> * * 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 * * 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 li.strolch.utils.helper; import java.math.BigDecimal; import java.math.RoundingMode; /** * A helper class that contains mathematical computations that can be used throughout. * * @author Martin Smock <smock.martin@gmail.com> * @author Michael Gatto <michael@gatto.ch> */ public class MathHelper { public static final double PRECISION = 1.0E08; public static final int PRECISION_DIGITS = 3; /** * Check if the two values are equal with respect to the precision * * @param firstValue * the first value to compare * @param secondValue * the second value to compare to * @return boolean True, if the two values are equal under the set precision. Fales, otherwise. */ public static boolean isEqualPrecision(double firstValue, double secondValue) { return (java.lang.Math.abs(firstValue - secondValue) < (1.0d / PRECISION)); } /** * Comparison between the two values. Given the precision, this function determines if the given value is smaller * than the given bound. * <p> * Note: this implementation tests if the value < bound, and if this is not so, checks if the values are equal under * the precision. Thus, it's efficient whenever the value is expected to be smaller than the bound. * * @param value * The value to check * @param bound * The bound given * @return true, if value < bound under the given precision. False, otherwise. */ public static boolean isSmallerEqualPrecision(double value, double bound) { if (value < bound) return true; return isEqualPrecision(value, bound); } /** * Comparison between two values. Given the precision, this function determines if the given value is greater than * the given bound. * <p> * Note: This implementation tests if value > bound and, if it is so, if equality does NOT hold. Thus, it is * efficient whenever the value is not expected to be greater than the bound. * * @param value * The value to check * @param bound * The bound given. * @return true, if value > bound and the values do not test equal under precision. False, otherwise. */ public static boolean isGreaterPrecision(double value, double bound) { return (value > bound) && !isEqualPrecision(value, bound); } /** * <p> * Rounds the given double value to the number of decimals * </p> * * <p> * <b>Warning:</b> Do not use the returned value for further calculations. Always finish calculates and use one of * the following methods: * <ul> * <li>{@link #isEqualPrecision(double, double)},</li> * <li>{@link #isGreaterPrecision(double, double)} or</li> * <li>{@link #isSmallerEqualPrecision(double, double)}</li> * </ul> * to test on equality or greater than/ smaller than * </p> * * @param value * the double value to round * @param decimals * number of decimals * * @return the rounded number */ public static double toPrecision(double value, int decimals) { if (value == 0.0) return 0.0; if (Double.isNaN(value)) return Double.NaN; if (value == Double.NEGATIVE_INFINITY) return Double.NEGATIVE_INFINITY; if (value == Double.POSITIVE_INFINITY) return Double.POSITIVE_INFINITY; return new BigDecimal(value).setScale(decimals, RoundingMode.HALF_EVEN).doubleValue(); } /** * Returns the value with the precision where precision is set to {@link #PRECISION_DIGITS} * * @see #toPrecision(double, int) */ public static double toPrecision(double value) { return toPrecision(value, PRECISION_DIGITS); } }