Reputation: 95
Given below the test code and its output. When I get float value from number value, precision is lost.. Can anyone tell me why this behaviour and also how to handle this?
public static void main(String[] args)
{
try
{
java.lang.Number numberVal = 676543.21;
float floatVal = numberVal.floatValue();
System.out.println("Number value : " + numberVal);
System.out.println("float value : " + floatVal);
System.out.println("Float.MAX_VALUE : " + Float.MAX_VALUE);
System.out.println("Is floatVal > Float.MAX_VALUE ? " + ( floatVal > Float.MAX_VALUE));
}catch(Exception e)
{
e.printStackTrace();
}
}
output:
Number value : 676543.21
float value : 676543.2
Float.MAX_VALUE : 3.4028235E38
Is floatVal > Float.MAX_VALUE ? false
also why the float value lesser than Float.MAX_VALUE?
Upvotes: 5
Views: 31431
Reputation: 16142
float
s are usually good up to 6 significant digits. Your number is 676543.21
which has 8 significant digits. You will see errors past 6 digits, and those errors will easily propagate to more significant digits the more calculations you perform. If you value your sanity (or precision), use double
s. Floats can't even count past 10 million accurately.
Now, you have 2 significant digits, which suggests to me that there is a chance you want to represent currency - DO NOT . Use your own class that internally represents values using fixed-point arithmetic.
Now, as to Float.MAX_VAL
which is 3.4028235E38, meaning 3.4028235*10^38 which is about 10^32 times larger than your value. Notice the 'E' in there? That's the exponent.
Upvotes: 26
Reputation: 2542
Decimal literals like the one you have typed default to type double
, not float
. java.lang.Number also uses doubles by default. If you were to replace that with java.lang.Number numberVal = 676543.21f;
I would expect the same level of precision loss from both. Alternatively, replace float floatVal = numberVal.floatValue();
with double doubleVal = numberVal.doubleValue();
In order not to lose precision.
EDIT, as an example, try running:
Number num = 676543.21;
System.out.println(num); //676543.21
System.out.println(num.doubleValue()); //676543.21
System.out.println(num.floatValue()); //676543.2 <= loses the precision
to see the difference in precision of the types
Float.MAX_VALUE
returns the largest value that a float can ever hold. any higher will overflow. If you look carefully, you'll see an 'E' in its textual representation. This is standard index form, that 'E' means "multiply by 10 to the power of whatever number follows the E" (or in java-speak *pow(10, numberAfterE))
Upvotes: 1
Reputation: 533442
All data types have representation limits so the fact there is a limit shouldn't be surprising.
float
uses 24-bit for its "mantissa" which holds all the significant digits. This means it has about 7 digits of precision (as 2^^24 is about 16 million)
double
uses 53-bit for it "mantissa" so it can hold about 16 digits accurately.
Upvotes: 9
Reputation: 6610
I love these. But I'll make it quick and painless.
Floats and decimals (aka floating points) aren't kept in the memory precisely either. But I don't want to get into float accuracy vs precision issues here, i'll just point you to a link - http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
As far as your other question, lemme put it this way, since floats are stored in scientific notation.
floatVal = 6.765432E6 = 6.7 * 10^6
MAX_VALUE = 3.4E38 = 3.4 * 10^38
MAX_VALUE is 32 orders of magnitude bigger than your float number. Feel free to take a look at here as well http://steve.hollasch.net/cgindex/coding/ieeefloat.html
I've spent a great deal of time comparing and fixing some FP issues a few months ago...
Try to use a small delta when comparing floats. Maybe this link will help you http://introcs.cs.princeton.edu/java/91float/
Upvotes: 9
Reputation: 10628
3.4028235E38 is greater than 676543.2. Float.MAX_VALUE is the largest float that is possible to represent.
Upvotes: 2