diff --git a/src/main/java/org/apache/commons/math/util/MathUtils.java b/src/main/java/org/apache/commons/math/util/MathUtils.java index ae7e251fa..d24459adb 100644 --- a/src/main/java/org/apache/commons/math/util/MathUtils.java +++ b/src/main/java/org/apache/commons/math/util/MathUtils.java @@ -17,12 +17,10 @@ package org.apache.commons.math.util; -import java.math.BigDecimal; import java.math.BigInteger; import java.util.Arrays; import org.apache.commons.math.exception.MathArithmeticException; -import org.apache.commons.math.exception.MathIllegalArgumentException; import org.apache.commons.math.exception.NotFiniteNumberException; import org.apache.commons.math.exception.NotPositiveException; import org.apache.commons.math.exception.NullArgumentException; @@ -233,177 +231,6 @@ public final class MathUtils { return a - p * FastMath.floor((a - offset) / p) - offset; } - /** - * Round the given value to the specified number of decimal places. The - * value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method. - * - * @param x the value to round. - * @param scale the number of digits to the right of the decimal point. - * @return the rounded value. - * @since 1.1 - */ - public static double round(double x, int scale) { - return round(x, scale, BigDecimal.ROUND_HALF_UP); - } - - /** - *
Round the given value to the specified number of decimal places. The - * value is rounded using the given method which is any method defined in - * {@link BigDecimal}.
- * - *If {@code x} is infinite or NaN, then the value of {@code x} is - * returned unchanged, regardless of the other parameters.
- * - * @param x the value to round. - * @param scale the number of digits to the right of the decimal point. - * @param roundingMethod the rounding method as defined in - * {@link BigDecimal}. - * @return the rounded value. - * @throws ArithmeticException if roundingMethod==ROUND_UNNECESSARY and the - * specified scaling operation would require rounding. - * @throws IllegalArgumentException if roundingMethod does not represent a - * valid rounding mode. - * @since 1.1 - */ - public static double round(double x, int scale, int roundingMethod) { - try { - return (new BigDecimal - (Double.toString(x)) - .setScale(scale, roundingMethod)) - .doubleValue(); - } catch (NumberFormatException ex) { - if (Double.isInfinite(x)) { - return x; - } else { - return Double.NaN; - } - } - } - - /** - * Round the given value to the specified number of decimal places. The - * value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method. - * - * @param x the value to round. - * @param scale the number of digits to the right of the decimal point. - * @return the rounded value. - * @since 1.1 - */ - public static float round(float x, int scale) { - return round(x, scale, BigDecimal.ROUND_HALF_UP); - } - - /** - * Round the given value to the specified number of decimal places. The - * value is rounded using the given method which is any method defined in - * {@link BigDecimal}. - * - * @param x the value to round. - * @param scale the number of digits to the right of the decimal point. - * @param roundingMethod the rounding method as defined in - * {@link BigDecimal}. - * @return the rounded value. - * @since 1.1 - */ - public static float round(float x, int scale, int roundingMethod) { - float sign = indicator(x); - float factor = (float)FastMath.pow(10.0f, scale) * sign; - return (float)roundUnscaled(x * factor, sign, roundingMethod) / factor; - } - - /** - * Round the given non-negative value to the "nearest" integer. Nearest is - * determined by the rounding method specified. Rounding methods are defined - * in {@link BigDecimal}. - * - * @param unscaled Value to round. - * @param sign Sign of the original, scaled value. - * @param roundingMethod Rounding method, as defined in {@link BigDecimal}. - * @return the rounded value. - * @throws MathIllegalArgumentException if {@code roundingMethod} is not a valid rounding method. - * @since 1.1 - */ - private static double roundUnscaled(double unscaled, - double sign, - int roundingMethod) { - switch (roundingMethod) { - case BigDecimal.ROUND_CEILING : - if (sign == -1) { - unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); - } else { - unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); - } - break; - case BigDecimal.ROUND_DOWN : - unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); - break; - case BigDecimal.ROUND_FLOOR : - if (sign == -1) { - unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); - } else { - unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); - } - break; - case BigDecimal.ROUND_HALF_DOWN : { - unscaled = FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY); - double fraction = unscaled - FastMath.floor(unscaled); - if (fraction > 0.5) { - unscaled = FastMath.ceil(unscaled); - } else { - unscaled = FastMath.floor(unscaled); - } - break; - } - case BigDecimal.ROUND_HALF_EVEN : { - double fraction = unscaled - FastMath.floor(unscaled); - if (fraction > 0.5) { - unscaled = FastMath.ceil(unscaled); - } else if (fraction < 0.5) { - unscaled = FastMath.floor(unscaled); - } else { - // The following equality test is intentional and needed for rounding purposes - if (FastMath.floor(unscaled) / 2.0 == FastMath.floor(Math - .floor(unscaled) / 2.0)) { // even - unscaled = FastMath.floor(unscaled); - } else { // odd - unscaled = FastMath.ceil(unscaled); - } - } - break; - } - case BigDecimal.ROUND_HALF_UP : { - unscaled = FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY); - double fraction = unscaled - FastMath.floor(unscaled); - if (fraction >= 0.5) { - unscaled = FastMath.ceil(unscaled); - } else { - unscaled = FastMath.floor(unscaled); - } - break; - } - case BigDecimal.ROUND_UNNECESSARY : - if (unscaled != FastMath.floor(unscaled)) { - throw new MathArithmeticException(); - } - break; - case BigDecimal.ROUND_UP : - unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); - break; - default : - throw new MathIllegalArgumentException(LocalizedFormats.INVALID_ROUNDING_METHOD, - roundingMethod, - "ROUND_CEILING", BigDecimal.ROUND_CEILING, - "ROUND_DOWN", BigDecimal.ROUND_DOWN, - "ROUND_FLOOR", BigDecimal.ROUND_FLOOR, - "ROUND_HALF_DOWN", BigDecimal.ROUND_HALF_DOWN, - "ROUND_HALF_EVEN", BigDecimal.ROUND_HALF_EVEN, - "ROUND_HALF_UP", BigDecimal.ROUND_HALF_UP, - "ROUND_UNNECESSARY", BigDecimal.ROUND_UNNECESSARY, - "ROUND_UP", BigDecimal.ROUND_UP); - } - return unscaled; - } - /** * Returns the sign * for byte value {@code x}. diff --git a/src/main/java/org/apache/commons/math/util/Precision.java b/src/main/java/org/apache/commons/math/util/Precision.java index f9b9fb9ff..edc86af62 100644 --- a/src/main/java/org/apache/commons/math/util/Precision.java +++ b/src/main/java/org/apache/commons/math/util/Precision.java @@ -17,6 +17,12 @@ package org.apache.commons.math.util; +import java.math.BigDecimal; +import org.apache.commons.math.exception.MathArithmeticException; +import org.apache.commons.math.exception.MathIllegalArgumentException; +import org.apache.commons.math.exception.util.LocalizedFormats; +import org.apache.commons.math.util.FastMath; + /** * Utilities for comparing numbers. * @@ -289,4 +295,172 @@ public class Precision { public static boolean equalsIncludingNaN(double x, double y, int maxUlps) { return (Double.isNaN(x) && Double.isNaN(y)) || equals(x, y, maxUlps); } + + /** + * Rounds the given value to the specified number of decimal places. + * The value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method. + * + * @param x Value to round. + * @param scale Number of digits to the right of the decimal point. + * @return the rounded value. + * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) + */ + public static double round(double x, int scale) { + return round(x, scale, BigDecimal.ROUND_HALF_UP); + } + + /** + * Rounds the given value to the specified number of decimal places. + * The value is rounded using the given method which is any method defined + * in {@link BigDecimal}. + * If {@code x} is infinite or {@code NaN}, then the value of {@code x} is + * returned unchanged, regardless of the other parameters. + * + * @param x Value to round. + * @param scale Number of digits to the right of the decimal point. + * @param roundingMethod Rounding method as defined in {@link BigDecimal}. + * @return the rounded value. + * @throws ArithmeticException if {@code roundingMethod == ROUND_UNNECESSARY} + * and the specified scaling operation would require rounding. + * @throws IllegalArgumentException if {@code roundingMethod} does not + * represent a valid rounding mode. + * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) + */ + public static double round(double x, int scale, int roundingMethod) { + try { + return (new BigDecimal + (Double.toString(x)) + .setScale(scale, roundingMethod)) + .doubleValue(); + } catch (NumberFormatException ex) { + if (Double.isInfinite(x)) { + return x; + } else { + return Double.NaN; + } + } + } + + /** + * Rounds the given value to the specified number of decimal places. + * The value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method. + * + * @param x Value to round. + * @param scale Number of digits to the right of the decimal point. + * @return the rounded value. + * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) + */ + public static float round(float x, int scale) { + return round(x, scale, BigDecimal.ROUND_HALF_UP); + } + + /** + * Rounds the given value to the specified number of decimal places. + * The value is rounded using the given method which is any method defined + * in {@link BigDecimal}. + * + * @param x Value to round. + * @param scale Number of digits to the right of the decimal point. + * @param roundingMethod Rounding method as defined in {@link BigDecimal}. + * @return the rounded value. + * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) + */ + public static float round(float x, int scale, int roundingMethod) { + final float sign = FastMath.copySign(1f, x); + final float factor = (float) FastMath.pow(10.0f, scale) * sign; + return (float) roundUnscaled(x * factor, sign, roundingMethod) / factor; + } + + /** + * Rounds the given non-negative value to the "nearest" integer. Nearest is + * determined by the rounding method specified. Rounding methods are defined + * in {@link BigDecimal}. + * + * @param unscaled Value to round. + * @param sign Sign of the original, scaled value. + * @param roundingMethod Rounding method, as defined in {@link BigDecimal}. + * @return the rounded value. + * @throws MathIllegalArgumentException if {@code roundingMethod} is not a valid rounding method. + * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) + */ + private static double roundUnscaled(double unscaled, + double sign, + int roundingMethod) { + switch (roundingMethod) { + case BigDecimal.ROUND_CEILING : + if (sign == -1) { + unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); + } else { + unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); + } + break; + case BigDecimal.ROUND_DOWN : + unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); + break; + case BigDecimal.ROUND_FLOOR : + if (sign == -1) { + unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); + } else { + unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY)); + } + break; + case BigDecimal.ROUND_HALF_DOWN : { + unscaled = FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY); + double fraction = unscaled - FastMath.floor(unscaled); + if (fraction > 0.5) { + unscaled = FastMath.ceil(unscaled); + } else { + unscaled = FastMath.floor(unscaled); + } + break; + } + case BigDecimal.ROUND_HALF_EVEN : { + double fraction = unscaled - FastMath.floor(unscaled); + if (fraction > 0.5) { + unscaled = FastMath.ceil(unscaled); + } else if (fraction < 0.5) { + unscaled = FastMath.floor(unscaled); + } else { + // The following equality test is intentional and needed for rounding purposes + if (FastMath.floor(unscaled) / 2.0 == FastMath.floor(Math + .floor(unscaled) / 2.0)) { // even + unscaled = FastMath.floor(unscaled); + } else { // odd + unscaled = FastMath.ceil(unscaled); + } + } + break; + } + case BigDecimal.ROUND_HALF_UP : { + unscaled = FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY); + double fraction = unscaled - FastMath.floor(unscaled); + if (fraction >= 0.5) { + unscaled = FastMath.ceil(unscaled); + } else { + unscaled = FastMath.floor(unscaled); + } + break; + } + case BigDecimal.ROUND_UNNECESSARY : + if (unscaled != FastMath.floor(unscaled)) { + throw new MathArithmeticException(); + } + break; + case BigDecimal.ROUND_UP : + unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY)); + break; + default : + throw new MathIllegalArgumentException(LocalizedFormats.INVALID_ROUNDING_METHOD, + roundingMethod, + "ROUND_CEILING", BigDecimal.ROUND_CEILING, + "ROUND_DOWN", BigDecimal.ROUND_DOWN, + "ROUND_FLOOR", BigDecimal.ROUND_FLOOR, + "ROUND_HALF_DOWN", BigDecimal.ROUND_HALF_DOWN, + "ROUND_HALF_EVEN", BigDecimal.ROUND_HALF_EVEN, + "ROUND_HALF_UP", BigDecimal.ROUND_HALF_UP, + "ROUND_UNNECESSARY", BigDecimal.ROUND_UNNECESSARY, + "ROUND_UP", BigDecimal.ROUND_UP); + } + return unscaled; + } } diff --git a/src/test/java/org/apache/commons/math/util/MathUtilsTest.java b/src/test/java/org/apache/commons/math/util/MathUtilsTest.java index 17504d3ca..bfd1578f6 100644 --- a/src/test/java/org/apache/commons/math/util/MathUtilsTest.java +++ b/src/test/java/org/apache/commons/math/util/MathUtilsTest.java @@ -241,212 +241,6 @@ public final class MathUtilsTest { } } - @Test - public void testRoundDouble() { - double x = 1.234567890; - Assert.assertEquals(1.23, MathUtils.round(x, 2), 0.0); - Assert.assertEquals(1.235, MathUtils.round(x, 3), 0.0); - Assert.assertEquals(1.2346, MathUtils.round(x, 4), 0.0); - - // JIRA MATH-151 - Assert.assertEquals(39.25, MathUtils.round(39.245, 2), 0.0); - Assert.assertEquals(39.24, MathUtils.round(39.245, 2, BigDecimal.ROUND_DOWN), 0.0); - double xx = 39.0; - xx = xx + 245d / 1000d; - Assert.assertEquals(39.25, MathUtils.round(xx, 2), 0.0); - - // BZ 35904 - Assert.assertEquals(30.1d, MathUtils.round(30.095d, 2), 0.0d); - Assert.assertEquals(30.1d, MathUtils.round(30.095d, 1), 0.0d); - Assert.assertEquals(33.1d, MathUtils.round(33.095d, 1), 0.0d); - Assert.assertEquals(33.1d, MathUtils.round(33.095d, 2), 0.0d); - Assert.assertEquals(50.09d, MathUtils.round(50.085d, 2), 0.0d); - Assert.assertEquals(50.19d, MathUtils.round(50.185d, 2), 0.0d); - Assert.assertEquals(50.01d, MathUtils.round(50.005d, 2), 0.0d); - Assert.assertEquals(30.01d, MathUtils.round(30.005d, 2), 0.0d); - Assert.assertEquals(30.65d, MathUtils.round(30.645d, 2), 0.0d); - - Assert.assertEquals(1.24, MathUtils.round(x, 2, BigDecimal.ROUND_CEILING), 0.0); - Assert.assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_CEILING), 0.0); - Assert.assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_CEILING), 0.0); - Assert.assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_CEILING), 0.0); - Assert.assertEquals(-1.234, MathUtils.round(-x, 3, BigDecimal.ROUND_CEILING), 0.0); - Assert.assertEquals(-1.2345, MathUtils.round(-x, 4, BigDecimal.ROUND_CEILING), 0.0); - - Assert.assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_DOWN), 0.0); - Assert.assertEquals(1.234, MathUtils.round(x, 3, BigDecimal.ROUND_DOWN), 0.0); - Assert.assertEquals(1.2345, MathUtils.round(x, 4, BigDecimal.ROUND_DOWN), 0.0); - Assert.assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0); - Assert.assertEquals(-1.234, MathUtils.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0); - Assert.assertEquals(-1.2345, MathUtils.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0); - - Assert.assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0); - Assert.assertEquals(1.234, MathUtils.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0); - Assert.assertEquals(1.2345, MathUtils.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0); - Assert.assertEquals(-1.24, MathUtils.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0); - Assert.assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0); - Assert.assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0); - - Assert.assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(1.234, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(-1.234, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); - - Assert.assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(1.234, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(-1.234, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(1.236, MathUtils.round(1.2355, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(-1.236, MathUtils.round(-1.2355, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - - Assert.assertEquals(1.23, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(-1.23, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(1.235, MathUtils.round(1.2345, 3, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(-1.235, MathUtils.round(-1.2345, 3, BigDecimal.ROUND_HALF_UP), 0.0); - - Assert.assertEquals(-1.23, MathUtils.round(-1.23, 2, BigDecimal.ROUND_UNNECESSARY), 0.0); - Assert.assertEquals(1.23, MathUtils.round(1.23, 2, BigDecimal.ROUND_UNNECESSARY), 0.0); - - try { - MathUtils.round(1.234, 2, BigDecimal.ROUND_UNNECESSARY); - Assert.fail(); - } catch (ArithmeticException ex) { - // expected - } - - Assert.assertEquals(1.24, MathUtils.round(x, 2, BigDecimal.ROUND_UP), 0.0); - Assert.assertEquals(1.235, MathUtils.round(x, 3, BigDecimal.ROUND_UP), 0.0); - Assert.assertEquals(1.2346, MathUtils.round(x, 4, BigDecimal.ROUND_UP), 0.0); - Assert.assertEquals(-1.24, MathUtils.round(-x, 2, BigDecimal.ROUND_UP), 0.0); - Assert.assertEquals(-1.235, MathUtils.round(-x, 3, BigDecimal.ROUND_UP), 0.0); - Assert.assertEquals(-1.2346, MathUtils.round(-x, 4, BigDecimal.ROUND_UP), 0.0); - - try { - MathUtils.round(1.234, 2, 1923); - Assert.fail(); - } catch (IllegalArgumentException ex) { - // expected - } - - // MATH-151 - Assert.assertEquals(39.25, MathUtils.round(39.245, 2, BigDecimal.ROUND_HALF_UP), 0.0); - - // special values - TestUtils.assertEquals(Double.NaN, MathUtils.round(Double.NaN, 2), 0.0); - Assert.assertEquals(0.0, MathUtils.round(0.0, 2), 0.0); - Assert.assertEquals(Double.POSITIVE_INFINITY, MathUtils.round(Double.POSITIVE_INFINITY, 2), 0.0); - Assert.assertEquals(Double.NEGATIVE_INFINITY, MathUtils.round(Double.NEGATIVE_INFINITY, 2), 0.0); - } - - @Test - public void testRoundFloat() { - float x = 1.234567890f; - Assert.assertEquals(1.23f, MathUtils.round(x, 2), 0.0); - Assert.assertEquals(1.235f, MathUtils.round(x, 3), 0.0); - Assert.assertEquals(1.2346f, MathUtils.round(x, 4), 0.0); - - // BZ 35904 - Assert.assertEquals(30.1f, MathUtils.round(30.095f, 2), 0.0f); - Assert.assertEquals(30.1f, MathUtils.round(30.095f, 1), 0.0f); - Assert.assertEquals(50.09f, MathUtils.round(50.085f, 2), 0.0f); - Assert.assertEquals(50.19f, MathUtils.round(50.185f, 2), 0.0f); - Assert.assertEquals(50.01f, MathUtils.round(50.005f, 2), 0.0f); - Assert.assertEquals(30.01f, MathUtils.round(30.005f, 2), 0.0f); - Assert.assertEquals(30.65f, MathUtils.round(30.645f, 2), 0.0f); - - Assert.assertEquals(1.24f, MathUtils.round(x, 2, BigDecimal.ROUND_CEILING), 0.0); - Assert.assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_CEILING), 0.0); - Assert.assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_CEILING), 0.0); - Assert.assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_CEILING), 0.0); - Assert.assertEquals(-1.234f, MathUtils.round(-x, 3, BigDecimal.ROUND_CEILING), 0.0); - Assert.assertEquals(-1.2345f, MathUtils.round(-x, 4, BigDecimal.ROUND_CEILING), 0.0); - - Assert.assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_DOWN), 0.0); - Assert.assertEquals(1.234f, MathUtils.round(x, 3, BigDecimal.ROUND_DOWN), 0.0); - Assert.assertEquals(1.2345f, MathUtils.round(x, 4, BigDecimal.ROUND_DOWN), 0.0); - Assert.assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0); - Assert.assertEquals(-1.234f, MathUtils.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0); - Assert.assertEquals(-1.2345f, MathUtils.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0); - - Assert.assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0); - Assert.assertEquals(1.234f, MathUtils.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0); - Assert.assertEquals(1.2345f, MathUtils.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0); - Assert.assertEquals(-1.24f, MathUtils.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0); - Assert.assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0); - Assert.assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0); - - Assert.assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(1.234f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); - Assert.assertEquals(-1.234f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); - - Assert.assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(1.234f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(-1.234f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(1.236f, MathUtils.round(1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - Assert.assertEquals(-1.236f, MathUtils.round(-1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); - - Assert.assertEquals(1.23f, MathUtils.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(-1.23f, MathUtils.round(-x, 2, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(1.235f, MathUtils.round(1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0); - Assert.assertEquals(-1.235f, MathUtils.round(-1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0); - - Assert.assertEquals(-1.23f, MathUtils.round(-1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0); - Assert.assertEquals(1.23f, MathUtils.round(1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0); - - try { - MathUtils.round(1.234f, 2, BigDecimal.ROUND_UNNECESSARY); - Assert.fail(); - } catch (MathArithmeticException ex) { - // success - } - - Assert.assertEquals(1.24f, MathUtils.round(x, 2, BigDecimal.ROUND_UP), 0.0); - Assert.assertEquals(1.235f, MathUtils.round(x, 3, BigDecimal.ROUND_UP), 0.0); - Assert.assertEquals(1.2346f, MathUtils.round(x, 4, BigDecimal.ROUND_UP), 0.0); - Assert.assertEquals(-1.24f, MathUtils.round(-x, 2, BigDecimal.ROUND_UP), 0.0); - Assert.assertEquals(-1.235f, MathUtils.round(-x, 3, BigDecimal.ROUND_UP), 0.0); - Assert.assertEquals(-1.2346f, MathUtils.round(-x, 4, BigDecimal.ROUND_UP), 0.0); - - try { - MathUtils.round(1.234f, 2, 1923); - Assert.fail(); - } catch (MathIllegalArgumentException ex) { - // success - } - - // special values - TestUtils.assertEquals(Float.NaN, MathUtils.round(Float.NaN, 2), 0.0f); - Assert.assertEquals(0.0f, MathUtils.round(0.0f, 2), 0.0f); - Assert.assertEquals(Float.POSITIVE_INFINITY, MathUtils.round(Float.POSITIVE_INFINITY, 2), 0.0f); - Assert.assertEquals(Float.NEGATIVE_INFINITY, MathUtils.round(Float.NEGATIVE_INFINITY, 2), 0.0f); - } - @Test public void testSignByte() { Assert.assertEquals((byte) 1, MathUtils.sign((byte) 2)); diff --git a/src/test/java/org/apache/commons/math/util/PrecisionTest.java b/src/test/java/org/apache/commons/math/util/PrecisionTest.java index 2e303b7ff..4c616d0b9 100644 --- a/src/test/java/org/apache/commons/math/util/PrecisionTest.java +++ b/src/test/java/org/apache/commons/math/util/PrecisionTest.java @@ -13,6 +13,11 @@ */ package org.apache.commons.math.util; +import java.math.BigDecimal; +import org.apache.commons.math.exception.MathArithmeticException; +import org.apache.commons.math.exception.MathIllegalArgumentException; +import org.apache.commons.math.TestUtils; + import org.junit.Assert; import org.junit.Test; @@ -252,6 +257,211 @@ public class PrecisionTest { Assert.assertEquals(+1, Precision.compareTo(Double.MAX_VALUE, Double.NaN, Integer.MAX_VALUE)); Assert.assertEquals(+1, Precision.compareTo(Double.NaN, Double.MAX_VALUE, Integer.MAX_VALUE)); + } + @Test + public void testRoundDouble() { + double x = 1.234567890; + Assert.assertEquals(1.23, Precision.round(x, 2), 0.0); + Assert.assertEquals(1.235, Precision.round(x, 3), 0.0); + Assert.assertEquals(1.2346, Precision.round(x, 4), 0.0); + + // JIRA MATH-151 + Assert.assertEquals(39.25, Precision.round(39.245, 2), 0.0); + Assert.assertEquals(39.24, Precision.round(39.245, 2, BigDecimal.ROUND_DOWN), 0.0); + double xx = 39.0; + xx = xx + 245d / 1000d; + Assert.assertEquals(39.25, Precision.round(xx, 2), 0.0); + + // BZ 35904 + Assert.assertEquals(30.1d, Precision.round(30.095d, 2), 0.0d); + Assert.assertEquals(30.1d, Precision.round(30.095d, 1), 0.0d); + Assert.assertEquals(33.1d, Precision.round(33.095d, 1), 0.0d); + Assert.assertEquals(33.1d, Precision.round(33.095d, 2), 0.0d); + Assert.assertEquals(50.09d, Precision.round(50.085d, 2), 0.0d); + Assert.assertEquals(50.19d, Precision.round(50.185d, 2), 0.0d); + Assert.assertEquals(50.01d, Precision.round(50.005d, 2), 0.0d); + Assert.assertEquals(30.01d, Precision.round(30.005d, 2), 0.0d); + Assert.assertEquals(30.65d, Precision.round(30.645d, 2), 0.0d); + + Assert.assertEquals(1.24, Precision.round(x, 2, BigDecimal.ROUND_CEILING), 0.0); + Assert.assertEquals(1.235, Precision.round(x, 3, BigDecimal.ROUND_CEILING), 0.0); + Assert.assertEquals(1.2346, Precision.round(x, 4, BigDecimal.ROUND_CEILING), 0.0); + Assert.assertEquals(-1.23, Precision.round(-x, 2, BigDecimal.ROUND_CEILING), 0.0); + Assert.assertEquals(-1.234, Precision.round(-x, 3, BigDecimal.ROUND_CEILING), 0.0); + Assert.assertEquals(-1.2345, Precision.round(-x, 4, BigDecimal.ROUND_CEILING), 0.0); + + Assert.assertEquals(1.23, Precision.round(x, 2, BigDecimal.ROUND_DOWN), 0.0); + Assert.assertEquals(1.234, Precision.round(x, 3, BigDecimal.ROUND_DOWN), 0.0); + Assert.assertEquals(1.2345, Precision.round(x, 4, BigDecimal.ROUND_DOWN), 0.0); + Assert.assertEquals(-1.23, Precision.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0); + Assert.assertEquals(-1.234, Precision.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0); + Assert.assertEquals(-1.2345, Precision.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0); + + Assert.assertEquals(1.23, Precision.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0); + Assert.assertEquals(1.234, Precision.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0); + Assert.assertEquals(1.2345, Precision.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0); + Assert.assertEquals(-1.24, Precision.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0); + Assert.assertEquals(-1.235, Precision.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0); + Assert.assertEquals(-1.2346, Precision.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0); + + Assert.assertEquals(1.23, Precision.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(1.235, Precision.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(1.2346, Precision.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(-1.23, Precision.round(-x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(-1.235, Precision.round(-x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(-1.2346, Precision.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(1.234, Precision.round(1.2345, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(-1.234, Precision.round(-1.2345, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); + + Assert.assertEquals(1.23, Precision.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(1.235, Precision.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(1.2346, Precision.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(-1.23, Precision.round(-x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(-1.235, Precision.round(-x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(-1.2346, Precision.round(-x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(1.234, Precision.round(1.2345, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(-1.234, Precision.round(-1.2345, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(1.236, Precision.round(1.2355, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(-1.236, Precision.round(-1.2355, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + + Assert.assertEquals(1.23, Precision.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(1.235, Precision.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(1.2346, Precision.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(-1.23, Precision.round(-x, 2, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(-1.235, Precision.round(-x, 3, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(-1.2346, Precision.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(1.235, Precision.round(1.2345, 3, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(-1.235, Precision.round(-1.2345, 3, BigDecimal.ROUND_HALF_UP), 0.0); + + Assert.assertEquals(-1.23, Precision.round(-1.23, 2, BigDecimal.ROUND_UNNECESSARY), 0.0); + Assert.assertEquals(1.23, Precision.round(1.23, 2, BigDecimal.ROUND_UNNECESSARY), 0.0); + + try { + Precision.round(1.234, 2, BigDecimal.ROUND_UNNECESSARY); + Assert.fail(); + } catch (ArithmeticException ex) { + // expected + } + + Assert.assertEquals(1.24, Precision.round(x, 2, BigDecimal.ROUND_UP), 0.0); + Assert.assertEquals(1.235, Precision.round(x, 3, BigDecimal.ROUND_UP), 0.0); + Assert.assertEquals(1.2346, Precision.round(x, 4, BigDecimal.ROUND_UP), 0.0); + Assert.assertEquals(-1.24, Precision.round(-x, 2, BigDecimal.ROUND_UP), 0.0); + Assert.assertEquals(-1.235, Precision.round(-x, 3, BigDecimal.ROUND_UP), 0.0); + Assert.assertEquals(-1.2346, Precision.round(-x, 4, BigDecimal.ROUND_UP), 0.0); + + try { + Precision.round(1.234, 2, 1923); + Assert.fail(); + } catch (IllegalArgumentException ex) { + // expected + } + + // MATH-151 + Assert.assertEquals(39.25, Precision.round(39.245, 2, BigDecimal.ROUND_HALF_UP), 0.0); + + // special values + TestUtils.assertEquals(Double.NaN, Precision.round(Double.NaN, 2), 0.0); + Assert.assertEquals(0.0, Precision.round(0.0, 2), 0.0); + Assert.assertEquals(Double.POSITIVE_INFINITY, Precision.round(Double.POSITIVE_INFINITY, 2), 0.0); + Assert.assertEquals(Double.NEGATIVE_INFINITY, Precision.round(Double.NEGATIVE_INFINITY, 2), 0.0); + } + + @Test + public void testRoundFloat() { + float x = 1.234567890f; + Assert.assertEquals(1.23f, Precision.round(x, 2), 0.0); + Assert.assertEquals(1.235f, Precision.round(x, 3), 0.0); + Assert.assertEquals(1.2346f, Precision.round(x, 4), 0.0); + + // BZ 35904 + Assert.assertEquals(30.1f, Precision.round(30.095f, 2), 0.0f); + Assert.assertEquals(30.1f, Precision.round(30.095f, 1), 0.0f); + Assert.assertEquals(50.09f, Precision.round(50.085f, 2), 0.0f); + Assert.assertEquals(50.19f, Precision.round(50.185f, 2), 0.0f); + Assert.assertEquals(50.01f, Precision.round(50.005f, 2), 0.0f); + Assert.assertEquals(30.01f, Precision.round(30.005f, 2), 0.0f); + Assert.assertEquals(30.65f, Precision.round(30.645f, 2), 0.0f); + + Assert.assertEquals(1.24f, Precision.round(x, 2, BigDecimal.ROUND_CEILING), 0.0); + Assert.assertEquals(1.235f, Precision.round(x, 3, BigDecimal.ROUND_CEILING), 0.0); + Assert.assertEquals(1.2346f, Precision.round(x, 4, BigDecimal.ROUND_CEILING), 0.0); + Assert.assertEquals(-1.23f, Precision.round(-x, 2, BigDecimal.ROUND_CEILING), 0.0); + Assert.assertEquals(-1.234f, Precision.round(-x, 3, BigDecimal.ROUND_CEILING), 0.0); + Assert.assertEquals(-1.2345f, Precision.round(-x, 4, BigDecimal.ROUND_CEILING), 0.0); + + Assert.assertEquals(1.23f, Precision.round(x, 2, BigDecimal.ROUND_DOWN), 0.0); + Assert.assertEquals(1.234f, Precision.round(x, 3, BigDecimal.ROUND_DOWN), 0.0); + Assert.assertEquals(1.2345f, Precision.round(x, 4, BigDecimal.ROUND_DOWN), 0.0); + Assert.assertEquals(-1.23f, Precision.round(-x, 2, BigDecimal.ROUND_DOWN), 0.0); + Assert.assertEquals(-1.234f, Precision.round(-x, 3, BigDecimal.ROUND_DOWN), 0.0); + Assert.assertEquals(-1.2345f, Precision.round(-x, 4, BigDecimal.ROUND_DOWN), 0.0); + + Assert.assertEquals(1.23f, Precision.round(x, 2, BigDecimal.ROUND_FLOOR), 0.0); + Assert.assertEquals(1.234f, Precision.round(x, 3, BigDecimal.ROUND_FLOOR), 0.0); + Assert.assertEquals(1.2345f, Precision.round(x, 4, BigDecimal.ROUND_FLOOR), 0.0); + Assert.assertEquals(-1.24f, Precision.round(-x, 2, BigDecimal.ROUND_FLOOR), 0.0); + Assert.assertEquals(-1.235f, Precision.round(-x, 3, BigDecimal.ROUND_FLOOR), 0.0); + Assert.assertEquals(-1.2346f, Precision.round(-x, 4, BigDecimal.ROUND_FLOOR), 0.0); + + Assert.assertEquals(1.23f, Precision.round(x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(1.235f, Precision.round(x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(1.2346f, Precision.round(x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(-1.23f, Precision.round(-x, 2, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(-1.235f, Precision.round(-x, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(-1.2346f, Precision.round(-x, 4, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(1.234f, Precision.round(1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); + Assert.assertEquals(-1.234f, Precision.round(-1.2345f, 3, BigDecimal.ROUND_HALF_DOWN), 0.0); + + Assert.assertEquals(1.23f, Precision.round(x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(1.235f, Precision.round(x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(1.2346f, Precision.round(x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(-1.23f, Precision.round(-x, 2, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(-1.235f, Precision.round(-x, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(-1.2346f, Precision.round(-x, 4, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(1.234f, Precision.round(1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(-1.234f, Precision.round(-1.2345f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(1.236f, Precision.round(1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + Assert.assertEquals(-1.236f, Precision.round(-1.2355f, 3, BigDecimal.ROUND_HALF_EVEN), 0.0); + + Assert.assertEquals(1.23f, Precision.round(x, 2, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(1.235f, Precision.round(x, 3, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(1.2346f, Precision.round(x, 4, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(-1.23f, Precision.round(-x, 2, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(-1.235f, Precision.round(-x, 3, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(-1.2346f, Precision.round(-x, 4, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(1.235f, Precision.round(1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0); + Assert.assertEquals(-1.235f, Precision.round(-1.2345f, 3, BigDecimal.ROUND_HALF_UP), 0.0); + + Assert.assertEquals(-1.23f, Precision.round(-1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0); + Assert.assertEquals(1.23f, Precision.round(1.23f, 2, BigDecimal.ROUND_UNNECESSARY), 0.0); + + try { + Precision.round(1.234f, 2, BigDecimal.ROUND_UNNECESSARY); + Assert.fail(); + } catch (MathArithmeticException ex) { + // success + } + + Assert.assertEquals(1.24f, Precision.round(x, 2, BigDecimal.ROUND_UP), 0.0); + Assert.assertEquals(1.235f, Precision.round(x, 3, BigDecimal.ROUND_UP), 0.0); + Assert.assertEquals(1.2346f, Precision.round(x, 4, BigDecimal.ROUND_UP), 0.0); + Assert.assertEquals(-1.24f, Precision.round(-x, 2, BigDecimal.ROUND_UP), 0.0); + Assert.assertEquals(-1.235f, Precision.round(-x, 3, BigDecimal.ROUND_UP), 0.0); + Assert.assertEquals(-1.2346f, Precision.round(-x, 4, BigDecimal.ROUND_UP), 0.0); + + try { + Precision.round(1.234f, 2, 1923); + Assert.fail(); + } catch (MathIllegalArgumentException ex) { + // success + } + + // special values + TestUtils.assertEquals(Float.NaN, Precision.round(Float.NaN, 2), 0.0f); + Assert.assertEquals(0.0f, Precision.round(0.0f, 2), 0.0f); + Assert.assertEquals(Float.POSITIVE_INFINITY, Precision.round(Float.POSITIVE_INFINITY, 2), 0.0f); + Assert.assertEquals(Float.NEGATIVE_INFINITY, Precision.round(Float.NEGATIVE_INFINITY, 2), 0.0f); } }