skiboy825
asked on
Float/BigDecimal problem...
Im 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, Ive 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) ?
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, Ive 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());
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
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
Should have checked those links before I posted them from my bookmarks. The microsoft link doesn't work anymore.
Do
field.setText(String.format("%.2f", measureFact));
ASKER
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)?
>>How can I format the '1.2345679E7' to what I originally entered (12345678.91)?
See above ( http:#23673857 )
See above ( http:#23673857 )
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.
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
12345679.00
float value = 12345678.91f;
System.out.println(String.format("%.2f", value));
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
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
ASKER
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' ?
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' ?
you need to change the database type
ASKER
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. ??
ASKER
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. ??
>>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
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
ASKER
objects, the datatype in my Sql db is decimal. All this happens before I store into the db anyway.
how it is formatted in your code has nothing really to do with how it is stored in the database.
> BigDecimal newActual = BigDecimal.valueOf(oldActu al.doubleV alue());
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
> BigDecimal newActual = BigDecimal.valueOf(oldActu
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
You don't format it *before* it goes in the db, you format it just before you need to display it
ASKER
Sorry, I wasn't clear. I need to format it before it gets displayed.
>>Sorry, I wasn't clear. I need to format it before it gets displayed.
Then use the code i posted
Then use the code i posted
then do your formatting *after* you pull it from database
ASKER
CEHJ,
I tried your code, but it returns '12345679'
I tried your code, but it returns '12345679'
>>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?
Make sure you haven't put it into an int. Can you post the code you used?
check your using a suitable type in the database
ASKER
objects, the database type is 'decimal', with precision 13, scale 4.
cehj, i will post my code...
cehj, i will post my code...
ASKER
// 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
You can do
Float oldActual = measureFact.getActual();
float f = oldActual.floatValue();
String output = String.format("%.2f", f);
ASKER
hmm, it still outputs as '12345679.00'
That would happen naturally after rounding to two DP. How many do you want?
ASKER
i want 2 decimal places. it needs to show up as 12345678.91.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
and dont't use getFloat() to get it from database
ASKER
I was afraid of that. Thanks for the help.
Shows up where? All you need to do is format it before displaying it