Problem description
In the project using Java to do floating-point calculation, found that for 4.015*100 such a calculation, the result is not expected to 401.5, but 401.49999999999994. Such a long number of digits is unfriendly to the display.
Problem reason: floating-point number representation
Check the relevant data, found that the reason is: the computer in the floating-point number is not fully accurate representation. For example, for a double type, 38414.4来 says, the computer stores it this way:
Convert to binary: 1001011000001110.0110011001100110011001100110011001100
Turn into a branch
Learning Counting Method: 1.0010110000011100110011001100110011001100110011001100x2^15
The double encoding format is this:
Double sign bit 1-bit order 11-bit mantissa 52-bit
Sign bit: Positive number unification is 0
Step code: 15 is a positive number, so the highest bit is 1, the lowest bit minus 1, 10000001110
Mantissa: Remove the highest bit default of 1, to 0010110000011100110011001100110011001100110011001100
Together, the resulting code is: 0 10000001110 0010110000011100110011001100110011001100110011001100
As can be seen from here, the main reason is that the binary code makes the decimal parts can not be fully accurate representation, such as 0.4 = 0.25 + 0.125 + ..., only infinitely close. Therefore, the calculation of floating-point number will produce precision error.
Solution: High Precision
BigDecimal in Java can support arbitrary-precision floating-point operations. In the book effective Java, it is suggested that float and double be used for scientific calculations or engineering calculations, while Java.math.BigDecimal are used in commercial calculations.
BigDecimal has a number of construction methods, such as BigDecimal (double), BigDecimal (string), and note that the construction parameter is a String type to guarantee no loss of precision because the double type itself is not completely accurate. So it needs to be written like this: BigDecimal ("0.02").
The basic operation of the double type can find the corresponding method in the BigDecimal. In addition, BigDecimal can also cooperate with NumberFormat to do formatted output.
BigDecimal generates new BigDecimal objects when doing operations, so there is more performance overhead relative to double.
A preliminary study on high precision implementation
So how does bigdecimal make it possible to express arbitrary precision? Here is only a preliminary analysis.
First look at the realization of BigInteger. The average int is 32 bits, so there is a range limit. BigInteger has the member variable int[] mag, so the variable length int array makes it possible to represent integers of any size.
Then look at the realization of BigDecimal. Its official introduction said that any one of the bigdecimal could be expressed as a unscaledvaluex10^-scale form. Unscaledvalue is an arbitrary size integer, in the source code corresponding BigInteger intval This member variable, scale is the order, in the source code corresponding to the int scale this variable. In this way, we get the realization of bigdecimal on the basis of BigInteger.
The above is a small set of Java in the solution to the problem of floating-point precision, I hope to help you, if you have any questions welcome to my message.