When you are calculating money, please watch!!! Don't regret the loss!!!
phenomena 1 :
public static void Main (string[] args) { System. out. println (0.030*100);//Output 3.0 System. out. println (0.031*100);//Output 3.1 System. out. println (0.032*100);//Output 3.2 System. out. println (0.033*100);//Output 3.3000000000000003 System. out. println (0.034*100);//Output 3.4000000000000004 System. out. println (0.035*100);//Output 3.5000000000000004 System. out. println (0.036*100);//Output 3.5999999999999996 System. out. println (0.037*100);//Output 3.6999999999999997 System. out. println (0.038*100);//Output 3.8 System. out. println (0.039*100);//Output 3.9 } |
phenomena 2 :
public static void Main (string[] args) { BigDecimal B1 = new BigDecimal ("0.236"); BigDecimal b2 = new BigDecimal (0.236); System. out. println (B1);//Output 0.236 System. out. println (B2);//Output 0.2359999999999999875655021241982467472553253173828125 } |
Describe:
When we use some "special numbers" for the operation, or call BigDecimal in the new BigDecimal (double val) to construct, you will get unexpected results.
Reason:
In Java, floating-point types are based on the IEEE754 standard. IEEE754 defines both 32-bit and 64-bit double-precision floating-point binary decimal standards. It is inaccurate to use binary notation for floating-point numbers such as Double,float.
At the same time, BigDecimal's API declaration is proposed to be constructed using new BigDecimal (String val), and when constructed with the new BigDecimal (double val), you will get unexpected results (the results of This constructor can somewhat unpredictable).
workaround (Take 0.236*100 = 23.599999999999998 For example):
1. Convert by string combined with BigDecimal.
String val = "0.236"; Constructed using the new BigDecimal (String val) BigDecimal a = new BigDecimal ("" +val); BigDecimal B = new BigDecimal ("" +100); The number of decimal places is consistent with the number of bits in the construction parameter System. out. println (a.multiply (b));//Output 23.600 |
2, by shifting the combination of BigDecimal to convert
String val = "0.236"; Constructed using the new BigDecimal (String val) BigDecimal a = new BigDecimal ("" +val); Move right Two bits A = A.movepointright (2); System. out. println (a);//Output 23.6 |
3, using the method of preserving the decimal place to convert
double result = 0.236*100; System. out. println (result);//Output 23.599999999999998 The calculation retains the result after the decimal point of four bits, and so on, 1 after a few zeros is reserved after the decimal number. Two decimal places reserved as follows result = (double) (Math. Round(result*100)/100.0); System. out. println (result);//Output 23.6 |
4, use DecimalFormat to determine the number of digits after the decimal point
double val = 0.236*100; Two digits after the decimal point, if three bits are reserved for "#.000" DecimalFormat df = new decimalformat ("#.00"); String str = Df.format (val); System. out. println (Double. ValueOf(str));//Output 23.6 |
5 、-----Many ways, one can
Experience:
There are many ways to deal with such precision problems, as long as they are not calculated directly using floating-point numbers.
Additional:
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):
1-bit, sign bit |
Power (8-bit) |
Mantissa (32-bit) |
Double (64-bit):
1-bit, sign bit |
Power (11-bit) |
Mantissa (52-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 .
The accuracy of floating-point numbers in Java "Go"