Repository: commons-lang
Updated Branches:
  refs/heads/master 7fd021d82 -> d2fb3b086


LANG-1018: Fix precision loss on NumberUtils.createNumber(String) (closes #156)


Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/8d6bc0ca
Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/8d6bc0ca
Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/8d6bc0ca

Branch: refs/heads/master
Commit: 8d6bc0ca625f3a1a98b486541fa613b2fac4b41c
Parents: 7fd021d
Author: Nick Manley <nickmanle...@outlook.com>
Authored: Thu Jun 9 23:04:18 2016 -0500
Committer: pascalschumacher <pascalschumac...@gmx.net>
Committed: Sun Jun 12 13:23:55 2016 +0200

----------------------------------------------------------------------
 .../apache/commons/lang3/math/NumberUtils.java  | 26 ++++++++------------
 .../commons/lang3/math/NumberUtilsTest.java     |  4 +++
 2 files changed, 14 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-lang/blob/8d6bc0ca/src/main/java/org/apache/commons/lang3/math/NumberUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/lang3/math/NumberUtils.java 
b/src/main/java/org/apache/commons/lang3/math/NumberUtils.java
index 22dddf4..3d59057 100644
--- a/src/main/java/org/apache/commons/lang3/math/NumberUtils.java
+++ b/src/main/java/org/apache/commons/lang3/math/NumberUtils.java
@@ -491,9 +491,7 @@ public class NumberUtils {
         // if both e and E are present, this is caught by the checks on expPos 
(which prevent IOOBE)
         // and the parsing which will detect if e or E appear in a number due 
to using the wrong offset
 
-        int numDecimals = 0; // Check required precision (LANG-693)
         if (decPos > -1) { // there is a decimal point
-
             if (expPos > -1) { // there is an exponent
                 if (expPos < decPos || expPos > str.length()) { // prevents 
double exponent causing IOOBE
                     throw new NumberFormatException(str + " is not a valid 
number.");
@@ -503,7 +501,6 @@ public class NumberUtils {
                 dec = str.substring(decPos + 1);
             }
             mant = getMantissa(str, decPos);
-            numDecimals = dec.length(); // gets number of digits past the 
decimal to ensure no loss of precision for floating point numbers.
         } else {
             if (expPos > -1) {
                 if (expPos > str.length()) { // prevents double exponent 
causing IOOBE
@@ -599,26 +596,23 @@ public class NumberUtils {
         //Must be a Float, Double, BigDecimal
         final boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
         try {
-            if(numDecimals <= 7){// If number has 7 or fewer digits past the 
decimal point then make it a float
-                final Float f = createFloat(str);
-                if (!(f.isInfinite() || (f.floatValue() == 0.0F && 
!allZeros))) {
-                    return f;
-                }
+            final Float f = createFloat(str);
+            final Double d = createDouble(str);
+            if (!f.isInfinite()
+                    && !(f.floatValue() == 0.0F && !allZeros)
+                    && f.toString().equals(d.toString())) {
+                return f;
             }
-        } catch (final NumberFormatException nfe) { // NOPMD
-            // ignore the bad number
-        }
-        try {
-            if(numDecimals <= 16){// If number has between 8 and 16 digits 
past the decimal point then make it a double
-                final Double d = createDouble(str);
-                if (!(d.isInfinite() || (d.doubleValue() == 0.0D && 
!allZeros))) {
+            if (!d.isInfinite() && !(d.doubleValue() == 0.0D && !allZeros)) {
+                final BigDecimal b = createBigDecimal(str);
+                if (b.compareTo(BigDecimal.valueOf(d)) == 0) {
                     return d;
                 }
+                return b;
             }
         } catch (final NumberFormatException nfe) { // NOPMD
             // ignore the bad number
         }
-
         return createBigDecimal(str);
     }
 

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/8d6bc0ca/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java 
b/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java
index 236084b..e2143bd 100644
--- a/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java
@@ -242,6 +242,10 @@ public class NumberUtilsTest {
         final Number bigNum = NumberUtils.createNumber("-1.1E-700F");
         assertNotNull(bigNum);
         assertEquals(BigDecimal.class, bigNum.getClass());
+        
+        // LANG-1018
+        assertEquals("createNumber(String) LANG-1018 failed",
+                Double.valueOf("-160952.54"), 
NumberUtils.createNumber("-160952.54"));
     }
     
     @Test

Reply via email to