Solved

# Float/BigDecimal problem...

Posted on 2009-02-18
1,465 Views
Im having trouble with some float/decimal/double format issue.

I have a class called MeasureFact with a Float property, called actual.

When I enter a value in a textbox on a form, it gets stored into actual property in MeasureFact.

If I enter 123456.78, it stores correctly as 123456.78

But if I enter 12345678.91, it stores as 1.2345679E7

If I change the actual property in the MeasureFact class to a BigDecimal, it works no problem. But the thing is, Ive got so many lines of code where I have it set to Float. So its gonna be a pain to change it all over the place and then double check for bugs.

I was thinking I could just convert the Float actual to a BigDecimal before I store into the database, but it still shows up as 1.2345679E7. Is there a way to convert this value to the way I entered it on the form (12345678.91) ?

``````BigDecimal actual = BigDecimal.valueOf(measureFact.getActual().doubleValue());
``````
0
Question by:skiboy825

LVL 86

Expert Comment

>>but it still shows up as 1.2345679E7

Shows up where? All you need to do is format it before displaying it
0

LVL 19

Expert Comment

The Java Language Specification requires that floats and doubles conform to the IEEE-754 Floating Point specification for single and double-precision floating point numbers. This specification calls for decimal values to be represented as a sign, mantissa (significant digits), radix (or base) and exponent. The radix is always 2. So, ignoring the sign for the moment, values are represented in IEEE-754 format as

mantissa * 2 ^ exponent

As a direct result, _all_ float and double values are merely approximations of their decimal values. Some decimal values can be represented exactly in this scheme. Some cannot. So when working with floats and doubles (the Java primitives), one should never assume exact values. The primitives are best used when the representation errors are not significant and performance is of the utmost importance. If you want arbitrary precision decimal value representation and are willing or must take the performance hit to get it (as in financial calculations), use the java.math.BigDecimal class.

If you want more information on floating point values, you might look at the following sites. (The last is a page which shows how decimal floating point values are represented in 32-bit and 64-bit IEEE-754.)

http://www.research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html
http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html

Best regards,
Jim Cakalic
0

LVL 19

Expert Comment

Should have checked those links before I posted them from my bookmarks. The microsoft link doesn't work anymore.
0

LVL 86

Expert Comment

Do
``````field.setText(String.format("%.2f", measureFact));
``````
0

Author Comment

When I say it shows up as '1.2345679E7', i mean that the 'actual' variable in my code snippet still returns '1.2345679E7'. How can I format the '1.2345679E7' to what I originally entered (12345678.91)?

0

LVL 86

Expert Comment

>>How can I format the '1.2345679E7' to what I originally entered (12345678.91)?

See above ( http:#23673857 )
0

LVL 19

Expert Comment

Maybe I wasn't clear the first time. You can't store the value 12345678.91 in a float without losing precision. It gets rounded up to 12345679 because there aren't enough bits in the mantissa to hold all the significant digits. The way to store arbitrary precision decimal numbers is with the BigDecimal class.
0

LVL 19

Expert Comment

Perhaps another way to demonstrate is with the code snippet below. If you were to run this the result printed on the console would be:
12345679.00

``````    float value = 12345678.91f;

System.out.println(String.format("%.2f", value));
``````
0

LVL 92

Expert Comment

floating point numbers do not have an exact representation, read the following for more details.

http://mindprod.com/jgloss/floatingpoint.html

To store it in database with the required precision you will need to use a different data type, such as string or a number type that supports precision

0

Author Comment

Jim,

I converted my original Float value into a BigDecimal but it was still stored as '1.2345679E7'.  Since '1.2345679E7' is essentially a representation of '12345678.91', how can I format this to '12345678.91' ?
0

LVL 92

Expert Comment

you need to change the database type

0

Author Comment

``````			Float oldActual;

// 1. entered "12345678.91", gets stored into oldActual

// 2. But value stored inside oldActual is "1.2345679E7"

// 3. So I convert oldActual into a BigDecimal, newActual

BigDecimal newActual = BigDecimal.valueOf(measureFact.getActual().doubleValue());

// 4. newActual value is still "1.2345679E7"

// 5. I want to format "1.2345679E7" to "12345678.91"

// 6. ??
``````
0

Author Comment

ignore the post above... made small correction to code.
``````			Float oldActual;

// 1. entered "12345678.91", gets stored into oldActual

// 2. But value stored inside oldActual is "1.2345679E7"

// 3. So I convert oldActual into a BigDecimal, newActual

BigDecimal newActual = BigDecimal.valueOf(oldActual.doubleValue());

// 4. newActual value is still "1.2345679E7"

// 5. I want to format "1.2345679E7" to "12345678.91"

// 6. ??
``````
0

LVL 86

Expert Comment

>>how can I format this to '12345678.91'

I've already answered that. If you've got it as BigDecimal, then the easiest way is to call doubleValue on it with the code i posted earlier
0

Author Comment

objects, the datatype in my Sql db is decimal. All this happens before I store into the db anyway.
0

LVL 92

Expert Comment

how it is formatted in your code has nothing really  to do with how it is stored in the database.

>                         BigDecimal newActual = BigDecimal.valueOf(oldActual.doubleValue());

you should instead use the ctor that takes a string and use the *string* exactly as entered instead of first parsing it to a float

0

LVL 86

Expert Comment

You don't format it *before* it goes in the db, you format it just before you need to display it
0

Author Comment

Sorry, I wasn't clear. I need to format it before it gets displayed.
0

LVL 86

Expert Comment

>>Sorry, I wasn't clear. I need to format it before it gets displayed.

Then use the code i posted
0

LVL 92

Expert Comment

then do your formatting *after* you pull it from database

0

Author Comment

CEHJ,

I tried your code, but it returns '12345679'
0

LVL 86

Expert Comment

>>I tried your code, but it returns '12345679'

Make sure you haven't put it into an int. Can you post the code you used?
0

LVL 92

Expert Comment

check your using a suitable type in the database

0

Author Comment

objects, the database type is 'decimal', with precision 13, scale 4.

cehj, i will post my code...
0

Author Comment

``````// Entered "12345678.91"

Float oldActual = measureFact.getActual();

System.out.println(oldActual);

// Output: 1.2345679E7

BigDecimal newActual1 = new BigDecimal(oldActual.toString(), MathContext.DECIMAL32);

System.out.println(newActual1);

System.out.println(String.format("%.2f", newActual1));

// Output: 1.234568E+7

// Output: 12345680.00

BigDecimal newActual2 = new BigDecimal(oldActual.toString(), MathContext.DECIMAL64);

System.out.println(newActual2);

System.out.println(String.format("%.2f", newActual2));

// Output: 12345679

// Output: 12345679.00

BigDecimal newActual3 = new BigDecimal(oldActual.toString(), MathContext.DECIMAL128);

System.out.println(newActual3);

System.out.println(String.format("%.2f", newActual3));

// Output: 12345679

// Output: 12345679.00

BigDecimal newActual4 = new BigDecimal(oldActual.toString(), MathContext.UNLIMITED);

System.out.println(newActual4);

System.out.println(String.format("%.2f", newActual4));

// Output: 12345679

// Output: 12345679.00

BigDecimal newActual5 = new BigDecimal(oldActual.toString());

System.out.println(newActual5);

System.out.println(String.format("%.2f", newActual5));

// Output: 12345679

// Output: 12345679.00
``````
0

LVL 86

Expert Comment

You can do
``````Float oldActual = measureFact.getActual();

float f = oldActual.floatValue();

String output = String.format("%.2f", f);
``````
0

Author Comment

hmm, it still outputs as '12345679.00'
0

LVL 86

Expert Comment

That would happen naturally after rounding to two DP. How many do you want?
0

Author Comment

i want 2 decimal places.  it needs to show up as 12345678.91.
0

LVL 19

Accepted Solution

At the risk of repeating myself, you can't get there from here with float. Floats only have 6-7 digits of precision. Doubles have 15 so, in this one case, it would be possible. But the correct way to represent arbitrary precision decimal numbers is with BigDecimal. You need to do what you first suggested: go back and replace your use of float with BigDecimal so that the user input can be correctly captured.
0

LVL 92

Expert Comment

and dont't use getFloat() to get it from database

0

Author Closing Comment

I was afraid of that. Thanks for the help.
0

## Featured Post

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done withâ€¦
By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula wâ€¦
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Booleâ€¦
This video teaches viewers about errors in exception handling.