Java double and float loss accuracy issues

Source: Internet
Author: User

See: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt357

Due to improper use of float or double, there may be an issue of loss of precision. The problem probably can be understood by the following code:

  1. Public class Floatdoubletest {

  2. Public static void Main (string[] args) {

  3. float f = 20014999;

  4. Double d = f;

  5. Double d2 = 20014999;

  6. System.out.println ("f=" + f);

  7. System.out.println ("d=" + D);

  8. System.out.println ("d2=" + D2);

  9. }

  10. }

The results are as follows:

F=2.0015e7

D=2.0015e7

D2=2.0014999e7

From the output you can see that the double can correctly represent 20014999, and float has no way to represent 20014999, only to get an approximate value. The results are surprising. 20014999 such a small number cannot be expressed under float. So with this question, did a float and double learning, do a simple share, hope to help you understand the Java floating point number.

About Java for float and double

The Java language supports two basic floating-point types: float and double. The floating-point types of Java are based on the IEEE 754 standard. IEEE 754 defines both 32-bit and 64-bit double-precision floating-point binary decimal standards.

IEEE 754 uses scientific notation to represent floating-point numbers with a decimal number of 2. 32-bit floating-point numbers use 1-bit notation for the number, 8-bit to represent the exponent, and 23 bits to denote the mantissa, which is the fraction of the decimal. An exponent that is a signed integer can have positive or negative points. The fractional part is represented by a binary (base 2) decimal number. For 64-bit double-precision floating-point numbers, a 1-bit symbol representing the number, a 11-bit exponent, and a 52-bit indicating the mantissa. The following two graphs indicate:

Float (32-bit):

Double (64-bit):

are divided into three parts:

(1) A separate sign bit s directly encodes the symbol S.

(2) The power exponent E of the K-bit, the shift code representation.

(3) n bits of the decimal, the original code is indicated.

So why is it that 20014999 can't be correctly represented by float?

Combining the notation of float and double, the answer can be known by analyzing the binary representation of 20014999.

The following procedure can be used to derive a binary representation of 20014999 under double and float.

  1. Public class FloatDoubleTest3 {

  2. Public static void Main (string[] args) {

  3. Double d = 8;

  4. Long L = double.doubletolongbits (d);

  5. System.out.println (Long.tobinarystring (l));

  6. float F = 8;

  7. int i = float.floattointbits (f);

  8. System.out.println (integer.tobinarystring (i));

  9. }

  10. }

The output results are as follows:

double:100000101110011000101100111100101110000000000000000000000000000

float:1001011100110001011001111001100

The results of the output analysis are as follows. For a binary that does not double the left side of the symbol bit 0 just can get 64 bits of binary number. According to the notation of double, the number of symbols, power exponent and mantissa are divided into three parts as follows:

0 10000010111 0011000101100111100101110000000000000000000000000000

For float the left side of the sign bit 0 just can get 32 bit binary number. According to the notation of float, the number of symbols, power exponent and mantissa are also divided into three parts as follows:

0 10010111 00110001011001111001100

The green part is the sign bit, the red part is the power exponent, the blue part is the mantissa.

The comparison can be drawn: The sign bit is 0, the power exponent is the shift code representation, both are equal. The only difference is the mantissa.

The mantissa in the double is: 001100010110011110010111 0000000000000000000000000000, omitting the subsequent 0, which requires at least 24 bits to be correctly represented.

And the mantissa below float is: 00110001011001111001100, total 23 bits.

Why is that? The reason is obvious, because the float mantissa can only represent 23 bits, so the 24-bit 001100010110011110010111 is rounded down to 23-bit 00110001011001111001100 under float. So 20014999 has become 20015000 under float.
That is to say that 20014999 is within the range of float, but the float representation in IEEE 754 has no way to represent 20014999, but only by rounding to get an approximate value.

Summarize:

Floating-point arithmetic is rarely accurate, as long as it exceeds the range of precision can be expressed error. Often the error is not due to the size of the number, but because of the precision of the number. Therefore, the resulting result is close but not equal to the desired result. Especially careful when using float and double for precise calculations.
There are some alternatives that you might consider implementing. such as BigDecimal by String or by using the long type.

Java double and float loss accuracy issues

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.