LANG-693 Method createNumber from NumberUtils doesn't work for floating point numbers other than Float

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/lang/trunk@1484263 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Sebastian Bazley 2013-05-19 10:22:13 +00:00
parent 64cfee77e3
commit 8a1042959d
3 changed files with 27 additions and 7 deletions

View File

@ -22,6 +22,7 @@
<body> <body>
<release version="3.2" date="TBA" description="Next release"> <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-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-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> <action issue="LANG-882" type="update">LookupTranslator now works with implementations of CharSequence other than String</action>

View File

@ -482,6 +482,7 @@ public static Number createNumber(final String str) throws NumberFormatException
// if both e and E are present, this is caught by the checks on expPos (which prevent IOOBE) // 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 // 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 (decPos > -1) { // there is a decimal point
if (expPos > -1) { // there is an exponent if (expPos > -1) { // there is an exponent
@ -493,6 +494,7 @@ public static Number createNumber(final String str) throws NumberFormatException
dec = str.substring(decPos + 1); dec = str.substring(decPos + 1);
} }
mant = str.substring(0, decPos); 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 { } else {
if (expPos > -1) { if (expPos > -1) {
if (expPos > str.length()) { // prevents double exponent causing IOOBE if (expPos > str.length()) { // prevents double exponent causing IOOBE
@ -588,18 +590,22 @@ public static Number createNumber(final String str) throws NumberFormatException
//Must be a Float, Double, BigDecimal //Must be a Float, Double, BigDecimal
final boolean allZeros = isAllZeros(mant) && isAllZeros(exp); final boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
try { 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); final Float f = createFloat(str);
if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) { if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
return f; return f;
} }
}
} catch (final NumberFormatException nfe) { // NOPMD } catch (final NumberFormatException nfe) { // NOPMD
// ignore the bad number // ignore the bad number
} }
try { 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); final Double d = createDouble(str);
if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) { if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
return d; return d;
} }
}
} catch (final NumberFormatException nfe) { // NOPMD } catch (final NumberFormatException nfe) { // NOPMD
// ignore the bad number // ignore the bad number
} }

View File

@ -116,6 +116,19 @@ public void testToFloatStringF() {
assertTrue("toFloat(String,int) 2 failed", NumberUtils.toFloat("a", 5.0f) == 5.0f); 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)}. * Test for {@link NumberUtils#toDouble(String)}.
*/ */