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 :
[Java]View Plaincopyprint?
- Public class Floatdoubletest {
- Public static void Main (string[] args) {
- float f = 20014999;
- Double d = f;
- Double d2 = 20014999;
- System.out.println ("f=" + f);
- System.out.println ("d=" + D);
- System.out.println ("d2=" + D2);
- }
- }
public class Floatdoubletest {public static void main (string[] args) {float F = 20014999;double d = f;double D2 = 20014999 ; System.out.println ("f=" + f); System.out.println ("d=" + D); System.out.println ("d2=" + D2);}}
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 the the float and double of Java
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 a52-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 20014999 float There is no way to express correctly?
combining float and double representations, by analysing 20014999 < Span style= "font-family:monospace;" >
The following procedure can be obtained 20014999 In double and f Loat The binary representation of the binary.
[Java]View Plaincopyprint?
- public class floatdoubletest3 {
- public static void main (string[] args) {
- double d = 8;&NBSP;&NBSP;
- long l = double.doubletolongbits (d);
- system.out.println (long.tobinarystring (L));
- float f = 8;&NBSP;&NBSP;
- int i = float.floattointbits (f);
- System.out.println (integer.tobinarystring (i));
- }&NBSP;&NBSP;
- }
public class FloatDoubleTest3 {public static void main (string[] args) {double d = 8;long L = double.doubletolongbits (d); System.out.println (Long.tobinarystring (l)); float F = 8;int i = float.floattointbits (f); System.out.println (integer.tobinarystring (i));}}
The output results are as follows:
double:100000101110011000101100111100101110000000000000000000000000000
float:1001011100110001011001111001100
double The binary left of the symbol bit 0 just to get 6 4
0 10000010111 0011000101100111100101110000000000000000000000000000
ForFloat Left to fill the symbol bit 0 According to the notation of float , also divided into Span style= "color: #000000;" >:
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.
< Span style= "Font-size:x-small;" > in double < Span style= "font-family:monospace;" > 001100010110011110010111 0000000000000000000000000000 , Omit the next 0, at least 24 bits to correctly represent
And the mantissa below float is: 00110001011001111001100 , Total .
Why is that? The reason is obvious becauseFloat Mantissacan represent up to23bit, so24Bit of001100010110011110010111InFloatThe following rounding turns into23Bit of00110001011001111001100。 So20014999InFloatThe following becomes20015000 。 That is to say 20014999 Although it is within the range of float, but in ieee 754 float notation precision length no way to represent 20014999 , and can only be rounded 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 in the usefloat and Double string combining bigdecimal or by using long
Why is the
Java float double precision lost? On the accuracy of floating-point numbers in Java "Go"