Double Precision when a float value is passed in d

2019-07-03 16:06发布

问题:

I have on question regarding double precision.When a float value is passed into double then I get some different result. For e.g.

float f= 54.23f;
double d1 = f;
System.out.println(d1);

The output is 54.22999954223633. Can someone explain the reason behind this behaviour. Is it like double defaults to 14 places of decimal precision.

回答1:

The same value is printed differently for float and double because the Java specification requires printing as many digits as needed to distinguish the value from adjacent representable values in the same type (per my answer here, and see the linked documentation for more precision in the definition).

Since float has fewer bits to represent values, and hence fewer values, they are spaced more widely apart, and you do not need as many digits to distinguish them. When you put the value into a double and print it, the Java rules require that more digits be printed so that the value is distinguished from nearby double values. The println function does not know that the value originally came from a float and does not contain as much information as can fit into a double.

54.23f is exactly 54.229999542236328125 (in hexadecimal, 0x1.b1d70ap+5). The float values just below and just above this are 54.2299957275390625 (0x1.b1d708p+5) and 54.23000335693359375 (0x1.b1d70cp+5). As you can see, printing “54.229999” would distinguish the value from 54.229995… and from 54.23…. However, the double values just below and just above 54.23f are 54.22999954223632101957264239899814128875732421875 and 54.22999954223633523042735760100185871124267578125. To distinguish the value, you need “54.22999954223633”.



回答2:

This is because the float hides the extra decimals and double shows them. The double will represent the actual number quite precisely and shows more digits.

Try this:

System.out.println(f.doubleValue()); (need to make it a Float first ofcourse)

So as you can see, the information is there, it is just rounded. Hope this helps



回答3:

This is due to the Internal Representation.
Floating-point numbers are typically packed into a computer datum as the sign bit, the exponent field, and the significand (mantissa), from left to right.

This is called as Accuracy Problems.
The fact that floating-point numbers cannot precisely represent all real numbers, and that floating-point operations cannot precisely represent true arithmetic operations, leads to many surprising situations. This is related to the finite precision with which computers generally represent numbers.

It is not a problem. It is how double works. You do not have to handle it and care about it. The precision of double is enough. Think, the difference between you number and the expected result is in the 14 position after decimal point.

If you need arbitrarily good precision, use the java.math.BigDecimal class.

Or if you still want to use double. Do like this:

double d = 5.5451521841;
NumberFormat nf = new DecimalFormat("##.###");
System.out.println(nf.format(d));

Please let me know in case of any doubt.



回答4:

Actually this is only about different visual representation or converting float / double to String. Let's take a look at internal binary representation

    float f = 0.23f;
    double d = f;
    System.out.println(Integer.toBinaryString(Float.floatToIntBits(f)));
    System.out.println(Long.toBinaryString(Double.doubleToLongBits(d)));

output

111110011010111000010100011111
11111111001101011100001010001111100000000000000000000000000000

it means that f was converted to d1 without any distortion, significant digits are the same



回答5:

double and float represent numbers in different formats.

Because of this you are bound to find certain numbers that store perfectly in one format but not in the other. You happen to have found one that correctly fits in a float but does not fit exactly in a `double.

This problem can also show itself when two different formatters are used.