### Thread: Error converting String to float

1. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Sep 2010
Posts
5
Rep Power
0

#### Error converting String to float

I thought the conversion from String to float would be very straightforward, but there is something going on here I don't understand.

When I run the following code:

<font size=2><pre>
String s = "834776.91";
System.out.println( "s = " + s);

float f = new Float(s + "f").floatValue();
System.out.println( "f = " + f);

double d = new Double(s + "d").doubleValue();
System.out.println( "d = " + d);
</pre></font>

I get the following output:

<font size=2><pre>
s = 834776.91
f = 834776.94
d = 834776.91
</pre></font>

Does anyone know why the value of f is ending up 834776.94 instead of 834776.91 ?

Thanks for any insight here!
2. I suspect your result has to do with both rounding and float precision. The bigger the int part of a float, the less precise the fractional part must be. There are only 32 bits in a float, after all!

Java Code:
```float f = 834776.91f;
System.out.printf("%f%n", f);   // 834776.937500
System.out.printf("%.4f%n", f); // 834776.9375
System.out.printf("%.2f%n", f); // 834776.94```

~

• codeJ agrees
3. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Sep 2010
Posts
5
Rep Power
0
Thanks Yawmark -- I can see that now.

I did look at the write-up you pointed me too regarding floating point arithmetic. Most of it was over my head, but the core of it in this situation seems to be the fractional part. The example about storing the decimal value 0.1 in a finite number of binary bits (no matter how many bits!) made this very clear.

I stumbled across this because I was using NumberFormat to represent a money amount -- stored as a number in Oracle, and returned as String -- as currency, and NumberFormat.format takes a double. Now I see that if the strings contain fractional parts, there is the potential for rounding whether I use a float or a double, depending, as you said, on the size of the int part. I could use BigDecimal, but then I don't know how to have NumberFormat represent this as currency, although because we only deal with US dollars, it is not difficult to do by hand.

Anyway, thanks very much!
4. You're welcome. As a related aside, the float and double data types should not be used for financial applications.

http://martinfowler.com/eaaCatalog/money.html

~
5. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Sep 2010
Posts
5
Rep Power
0
Hi Yawmark,

I took a look at the link -- there seems to be pretty universal agreement that float or data primitives are not suitable for money amounts. Some people recommend using BigDecimal and others working with cents using integers.

Most of our work is within an Oracle database, where the NUMBER datatype serves us quite well for money amounts. In this particular application, however, a jsp is used to render such an amount as currency. As I said -- for reasons I will omit here -- the number is returned from the database as a string, consisting of an integer part, optionally followed by a decimal point and one or two digits.

Since this application is small, and involves practically no calculations, but rather only rendering values from the database, I am currently using pretty much the following:
Code:
```NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US);
String val1 = "834776.91";
String val2 = "1234567898765432112345678987654321.91";
// following would actually be jsp expressions
System.out.println( nf.format( new BigDecimal(val1) ) );
System.out.println( nf.format( new BigDecimal(val2) ) );```
The article (above ) says that using BigDecimal is a bad bad idea for money amounts, but I'm not sure why, other than for performance reasons, which in this app are insignificant. I am not sure why using this construct works better, but it seems (so far) to be more likely to give accurate representations, even of unrealistically large numbers. I do have to admit, I am not entirely comfortable with this, because there is no format(Object) method in NumberFormat, so I suppose the BigDecimal is first being converted to double. The construct above, using implicit conversion, gives the intended results (for the examples), but if I use explicit conversion -- BigDecimal.doubleValue() -- rounding occurs for the larger number:

Code:
```System.out.println( nf.format( new BigDecimal(val1).doubleValue() ) );
System.out.println( nf.format( new BigDecimal(val2).doubleValue() ) );```
All of the numbers we are dealing with are less than a billion (\$1,000,000,000.00). Do you see an issue with my using BigDecimal and implicit conversion in the call to NumberFormat.Format()? If you agree with this article , do you know of any examples of taking such a string and converting it to cents and then using integers?

Thanks for any thoughts you have regarding this. It so sucks that Oracle bought Sun
6. The class NumberFormat is an extension of the class Format. This superclass has a method format(Object) which calls a 3 parameter format method of the extending class:
java Code:
```public final String format (Object obj) {
return format(obj, new StringBuffer(), new FieldPosition(0)).toString();
}```

While you might think you're using an instance of NumberFormat class, this method:
java Code:
`NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US);`

actually gives you an instance of java.text.DecimalFormat.

When you take a closer look at the above mentioned format method in DecimalFormat:

java Code:
```    public final StringBuffer format(Object number,
StringBuffer toAppendTo,
FieldPosition pos) {
if (number instanceof Long || number instanceof Integer ||
number instanceof Short || number instanceof Byte ||
number instanceof AtomicInteger ||
number instanceof AtomicLong ||
(number instanceof BigInteger &&
((BigInteger)number).bitLength () < 64)) {
return format(((Number)number).longValue(), toAppendTo, pos);
} else if (number instanceof BigDecimal) {
return format((BigDecimal)number, toAppendTo, pos);
} else if (number instanceof BigInteger) {
return format((BigInteger)number, toAppendTo, pos);
} else if (number instanceof Number) {
return format(((Number)number).doubleValue(), toAppendTo, pos);
} else {
throw new IllegalArgumentException("Cannot format given Object as a Number");
}
}```
You can see on line 11 and 12 that DecimalFormat has a method specific for formatting a BigDecimal. After this off course there is a whole lot more code, but trust me, doubleValue() of BigDecimal is not called once.

Another hint that NumberFormat does not implicitly call doubleValue() of BigDecimal is that doubelValue() gives you
Code:
`1.2345678987654321E33`
There is no way Format can dream up the remaining digits after this...

(First post in years, got to get me a new avatar)
Last edited by wsa1971; September 24th, 2010 at 05:14 PM.
7. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Sep 2010
Posts
5
Rep Power
0
Thanks very much wsa1971 -- that was an excellent explanation of what is going on here, as well as a good lesson for me in how to dig deeper (into inherited behavior as well as source code) to solve such problems! Help like this from you and Yawmark is very much appreciated :-)
8. You're welcome.
9. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Sep 2013
Posts
1
Rep Power
0

#### Complixe Code

Hello
every one i am new in Java Programming, how i need to convert this ( y=x2+6x+5 and second one: x2+x3+6x-5 ) to Java Programming code
there any one who help me regarding this Problem.

Thanks alot.