I recently studied Java's floating-point calculation issues, queried relevant information from the Internet, summarized and went through some sorting and debugging, and finally completed this article. Everyone is welcome to point out the errors and problems.
In Java, variables declared by float are single-precision floating-point numbers, and variables declared by double are double-precision floating-point numbers. As the name implies, double-type entities occupy twice the memory space of float. float is 4 bytes and double is 8 bytes. Float and double type data cannot accurately represent calculation results. This is because float and double are imprecise calculations. You can see this through the following code:
Copy the code code as follows:
public class Test
{
public static void main(String[] args)
{
System.out.println(0.05 + 0.01);
System.out.println(1.0 - 0.42);
System.out.println(4.015 * 100);
System.out.println(123.3 / 100);
}
}
The result of running is:
0.060000000000000005
0.5800000000000001
401.49999999999994
1.23299999999999999
To get the desired effect, we can try to use java.text.DecimalFormat to format floating point numbers:
DecimalFormat can format numbers according to a certain format. Commonly used formatting characters are #, 0, etc. example:
Copy the code code as follows:
System.out.println(new java.text.DecimalFormat("0.00").format(3.125));
System.out.println(new java.text.DecimalFormat("0.00").format(3.135));
But the result is:
3.12
3.14
This is because DecimalFormat uses half-even rounding (ROUND_HALF_EVEN). Simply put, it relies on the nearest even number when rounding to 5. Therefore, reliable floating point numbers cannot be obtained using DecimalForamt. Finally we can consider using BigDecimal for more accurate calculations:
BigDecimal provides multiple constructors, related to floating point numbers:
Copy the code code as follows:
BigDecimal(double val) Translates a double into a BigDecimal.
BigDecimal(String val) Translates the String repre sentation of a BigDecimal into a BigDecimal.
However, using double parameters to create objects will result in inaccurate values. Only creating objects through String is the most accurate.
For example:
Copy the code code as follows:
BigDecimal bd1=new BigDecimal(0.05);
System.out.println(bd1.toString());
BigDecimal bd2=new BigDecimal("0.05");
System.out.println(bd2.toString());
Get the result:
0.05000000000000000277555756156289135105907917022705078125
0.05
Therefore, we ultimately need to use String to create objects, so that the results obtained are the most accurate. In addition, if it is a double number, we can also use: BigDecimal.valueOf(double val). The reason is very simple. The JDK source code is as follows:
Copy the code code as follows:
public static BigDecimal valueOf(double val)
{
return new BigDecimal(Double.toString(val));
}
The last thing to note is: BigDecimal's addition, subtraction, multiplication and division actually ultimately return a new BigDecimal object. Because BigDecimal is immutable, a new object will be generated during each operation, so a .add(b); Although the addition operation is performed, a does not save the value after the addition operation. The correct usage should be a=a.add(b).