package iamrescue.util; import java.math.BigDecimal; import java.math.BigInteger; import org.apache.commons.lang.Validate; public class NumberUtils { private static int byteRange = Byte.MAX_VALUE - Byte.MIN_VALUE; private static int shortRange = Short.MAX_VALUE - Short.MIN_VALUE; /** * Converts a byte to a percentage (between 0.0 and 1.0), where * Byte.MIN_VALUE is mapped to 0.0 and Byte.MAX_VALUE is mapped to 1.0 * @param percentage * @return */ public static double convertByteToPercentage(byte b) { return (b - Byte.MIN_VALUE) / (double) byteRange; } /** * Converts a percentage (between 0.0 and 1.0) to a byte, where 0.0 is * mapped to Byte.MIN_VALUE and 1.0 is mapped to Byte.MAX_VALUE * @param percentage * @return */ public static byte convertPercentageToByte(double percentage) { if (percentage > 1 || percentage < 0) { throw new IllegalArgumentException("Value out of range " + percentage); } return (byte) (Math.round(percentage * byteRange) + Byte.MIN_VALUE); } public static boolean equals(Number object1, Number object2, double delta) { double d1 = object1.doubleValue(); double d2 = object2.doubleValue(); if (d1 == d2) { return true; } return (Math.max(d1, d2) / Math.min(d1, d2) - 1) < delta; } public static boolean almostEquals(Number number, Number number2, double d, int i) { if (!equals(number, number2, d)) { return (Math.abs(number.doubleValue() - number2.doubleValue()) < i); } else { return true; } } /** * Converts a byte to a percentage (between 0.0 and 1.0), where * Byte.MIN_VALUE is mapped to 0.0 and Byte.MAX_VALUE is mapped to 1.0 * @param percentage * @return */ public static double convertShortToPercentage(short b) { return (b - Short.MIN_VALUE) / (double) shortRange; } /** * Converts a percentage (between 0.0 and 1.0) to a byte, where 0.0 is * mapped to Byte.MIN_VALUE and 1.0 is mapped to Byte.MAX_VALUE * @param percentage * @return */ public static short convertPercentageToShort(double percentage) { if (percentage > 1 || percentage < 0) { throw new IllegalArgumentException("Value out of range " + percentage); } return (short) (Math.round(percentage * shortRange) + Short.MIN_VALUE); } public static double computePercentage(double value, double min, double max) { Validate.isTrue(value >= min); Validate.isTrue(value <= max); return (value - min) / (max - min); } public static double computeValue(double percentage, double min, double max) { return percentage * (max - min) + min; } /** * Convert the given number into an instance of the given target class. * Copied from org.springframework.util.NumberUtils * @param number * the number to convert * @param targetClass * the target class to convert to * @return the converted number * @throws IllegalArgumentException * if the target class is not supported (i.e. not a standard * Number subclass as included in the JDK) * @see java.lang.Byte * @see java.lang.Short * @see java.lang.Integer * @see java.lang.Long * @see java.math.BigInteger * @see java.lang.Float * @see java.lang.Double * @see java.math.BigDecimal */ public static Number convertNumberToTargetClass(Number number, Class targetClass) throws IllegalArgumentException { assert number != null : "Number must not be null"; assert targetClass != null : "Target class must not be null"; if (targetClass.isInstance(number)) { return number; } else if (targetClass.equals(Byte.class)) { long value = number.longValue(); if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { raiseOverflowException(number, targetClass); } return new Byte(number.byteValue()); } else if (targetClass.equals(Short.class)) { long value = number.longValue(); if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { raiseOverflowException(number, targetClass); } return new Short(number.shortValue()); } else if (targetClass.equals(Integer.class)) { long value = number.longValue(); if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { raiseOverflowException(number, targetClass); } return Integer.valueOf(number.intValue()); } else if (targetClass.equals(Long.class)) { return Long.valueOf(number.longValue()); } else if (targetClass.equals(Float.class)) { return Float.valueOf(number.floatValue()); } else if (targetClass.equals(Double.class)) { return Double.valueOf(number.doubleValue()); } else if (targetClass.equals(BigInteger.class)) { return BigInteger.valueOf(number.longValue()); } else if (targetClass.equals(BigDecimal.class)) { // using BigDecimal(String) here, to avoid unpredictability of // BigDecimal(double) // (see BigDecimal javadoc for details) return new BigDecimal(number.toString()); } else { throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" + number.getClass().getName() + "] to unknown target class [" + targetClass.getName() + "]"); } } /** * Raise an overflow exception for the given number and target class. * @param number * the number we tried to convert * @param targetClass * the target class we tried to convert to */ private static void raiseOverflowException(Number number, Class targetClass) { throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" + number.getClass().getName() + "] to target class [" + targetClass.getName() + "]: overflow"); } }