From e91d0f0510ee8d69c76ee89b4e57341418866c6b Mon Sep 17 00:00:00 2001 From: Thomas Neidhart Date: Thu, 16 Jan 2014 22:11:00 +0000 Subject: [PATCH] [MATH-1089] Precision.round(double, ...) will return negative zero for negative values rounded to zero. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1558933 13f79535-47bb-0310-9956-ffa450edef68 --- src/changes/changes.xml | 4 ++++ .../java/org/apache/commons/math3/util/Precision.java | 5 +++-- .../java/org/apache/commons/math3/util/PrecisionTest.java | 8 +++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index dbafe3a73..3cfc91588 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,10 @@ If the output is not quite correct, check for invisible trailing spaces! + + "Precision#round(double, ...)" will now return negative zero for negative + values rounded to zero, similar to the float variant. + The iterator returned by "MultiDimensionalCounter#iterator()" will now correctly throw a "NoSuchElementException" when calling "next()" and the diff --git a/src/main/java/org/apache/commons/math3/util/Precision.java b/src/main/java/org/apache/commons/math3/util/Precision.java index f0b0c4ff7..441e015ac 100644 --- a/src/main/java/org/apache/commons/math3/util/Precision.java +++ b/src/main/java/org/apache/commons/math3/util/Precision.java @@ -392,10 +392,11 @@ public class Precision { */ public static double round(double x, int scale, int roundingMethod) { try { - return (new BigDecimal - (Double.toString(x)) + final double rounded = (new BigDecimal(Double.toString(x)) .setScale(scale, roundingMethod)) .doubleValue(); + // MATH-1089: negative values rounded to zero should result in negative zero + return rounded == 0.0 ? rounded * FastMath.copySign(1d, x) : rounded; } catch (NumberFormatException ex) { if (Double.isInfinite(x)) { return x; diff --git a/src/test/java/org/apache/commons/math3/util/PrecisionTest.java b/src/test/java/org/apache/commons/math3/util/PrecisionTest.java index f73d11752..6b102eb5e 100644 --- a/src/test/java/org/apache/commons/math3/util/PrecisionTest.java +++ b/src/test/java/org/apache/commons/math3/util/PrecisionTest.java @@ -393,6 +393,9 @@ public class PrecisionTest { 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); + // comparison of positive and negative zero is not possible -> always equal thus do string comparison + Assert.assertEquals("-0.0", Double.toString(Precision.round(-0.0, 0))); + Assert.assertEquals("-0.0", Double.toString(Precision.round(-1e-10, 0))); } @Test @@ -490,7 +493,10 @@ public class PrecisionTest { 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); - + // comparison of positive and negative zero is not possible -> always equal thus do string comparison + Assert.assertEquals("-0.0", Float.toString(Precision.round(-0.0f, 0))); + Assert.assertEquals("-0.0", Float.toString(Precision.round(-1e-10f, 0))); + // MATH-1070 Assert.assertEquals(0.0f, Precision.round(0f, 2, BigDecimal.ROUND_UP), 0.0f); Assert.assertEquals(0.05f, Precision.round(0.05f, 2, BigDecimal.ROUND_UP), 0.0f);