You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2013/05/19 12:22:13 UTC

svn commit: r1484263 - in /commons/proper/lang/trunk/src: changes/changes.xml main/java/org/apache/commons/lang3/math/NumberUtils.java test/java/org/apache/commons/lang3/math/NumberUtilsTest.java

Author: sebb
Date: Sun May 19 10:22:13 2013
New Revision: 1484263

URL: http://svn.apache.org/r1484263
Log:
LANG-693 Method createNumber from NumberUtils doesn't work for floating point numbers other than Float

Modified:
    commons/proper/lang/trunk/src/changes/changes.xml
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/math/NumberUtils.java
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java

Modified: commons/proper/lang/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/changes/changes.xml?rev=1484263&r1=1484262&r2=1484263&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/changes/changes.xml (original)
+++ commons/proper/lang/trunk/src/changes/changes.xml Sun May 19 10:22:13 2013
@@ -22,6 +22,7 @@
   <body>
 
   <release version="3.2" date="TBA" description="Next release">
+    <action issue="LANG-693" type="fix" due-to="Calvin Echols">Method createNumber from NumberUtils doesn't work for floating point numbers other than Float</action>
     <action issue="LANG-887" type="fix">FastDateFormat does not use the locale specific cache correctly</action>
     <action issue="LANG-884" type="update">Simplify FastDateFormat; eliminate boxing</action>
     <action issue="LANG-882" type="update">LookupTranslator now works with implementations of CharSequence other than String</action>

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/math/NumberUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/math/NumberUtils.java?rev=1484263&r1=1484262&r2=1484263&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/math/NumberUtils.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/math/NumberUtils.java Sun May 19 10:22:13 2013
@@ -482,6 +482,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
@@ -493,6 +494,7 @@ public class NumberUtils {
                 dec = str.substring(decPos + 1);
             }
             mant = str.substring(0, 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
@@ -588,17 +590,21 @@ public class NumberUtils {
         //Must be a Float, Double, BigDecimal
         final boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
         try {
-            final Float f = createFloat(str);
-            if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
-                return f;
+            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;
+                }
             }
         } catch (final NumberFormatException nfe) { // NOPMD
             // ignore the bad number
         }
         try {
-            final Double d = createDouble(str);
-            if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
-                return d;
+            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))) {
+                    return d;
+                }
             }
         } catch (final NumberFormatException nfe) { // NOPMD
             // ignore the bad number

Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java?rev=1484263&r1=1484262&r2=1484263&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/math/NumberUtilsTest.java Sun May 19 10:22:13 2013
@@ -115,7 +115,20 @@ public class NumberUtilsTest {
         assertTrue("toFloat(String,int) 1 failed", NumberUtils.toFloat("1.2345", 5.1f) == 1.2345f);
         assertTrue("toFloat(String,int) 2 failed", NumberUtils.toFloat("a", 5.0f) == 5.0f);
     }
-
+    
+    /**
+     * Test for {(@link NumberUtils#createNumber(String)}
+     */
+    @Test
+    public void testStringCreateNumberEnsureNoPrecisionLoss(){
+        String shouldBeFloat = "1.23";
+        String shouldBeDouble = "3.40282354e+38";
+        String shouldBeBigDecimal = "1.797693134862315759e+308";
+        
+        assertTrue(NumberUtils.createNumber(shouldBeFloat) instanceof Float);
+        assertTrue(NumberUtils.createNumber(shouldBeDouble) instanceof Double);
+        assertTrue(NumberUtils.createNumber(shouldBeBigDecimal) instanceof BigDecimal);
+    }
     /**
      * Test for {@link NumberUtils#toDouble(String)}.
      */