The java.math package provides classes for manipulating large numbers for highly precise calculations, such as the BigInteger, BigDecimal classes. Float and double, which we use most often in development, are only suitable for general scientific and engineering calculations, and there is a corresponding loss of precision when using float and double for more precise calculations such as currency, making the BigDecimal class necessary for precise calculations of large numbers. BigDecimal is therefore suitable for commercial computing scenarios where it is used to perform precise calculations on numbers that exceed 16 significant bits. But BigDecimal is not used in the same way as float and double, and the consequences of using BigDecimal incorrectly are more serious. Here are some examples of BigDecimal failures in our projects:

Loss of initialization accuracy for BigDecimal

Let’s start with the following code:

BigDecimal bd1 = new BigDecimal(0.1); System.out.println("bd1="+bd1); BigDecimal bd2 = new BigDecimal("0.1"); System.out.println("bd2="+bd2); BigDecimal bd3 = BigDecimal. The valueOf (0.1); System.out.println("bd3="+bd3);Copy the code

Output result:

Bd1 = 0.1000000000000000055511151231257827021181583404541015625 0.1 bd3 bd2 = = 0.1Copy the code

If a float or double is converted to Bigdecimal, do not use the New Bigdecimal () conversion, but use the valueOf() method or new Bigdecimal (“”) conversion to String, otherwise accuracy problems may occur.

The book Effective Java says:

If you need an exact answer, avoid floats and doubles

Because float and double perform binary floating-point operations, binary can sometimes misrepresent a decimal, just as decimal can misrepresent 1/3(1/3=0.3333…). That is, the binary representation of decimals can only represent any combination of the sum of 1/(2^n), for example:

0.5 can be represented because it can be represented as 1/2

0.75 can also be expressed because it can be expressed as 1/2+1/(2^2).

0.875 can also be expressed because it can be expressed as 1/2+1/(2^2)+1/(2^3).

But 0.1 cannot be expressed precisely because it cannot be expressed as a sum of 1/(2^n)

System. The out. Println (0.5 * 3); System. The out. Println (0.1 * 3);Copy the code

You can run these two lines of code locally and see the output to see why binary can represent 0.5 instead of 0.1. So it’s not really a BigDecimal problem, BigDecimal exists for exact computation, and the problem is that 0.1 is inherently an inaccurate value, which has nothing to do with BigDecimal, but needs to be used with care.

BigDecimal must set precision when performing division operations, otherwise it will throw an exception if it can’t divide enough

Proceed to the following code execution result:

BigDecimal bd4 = new BigDecimal("10");
BigDecimal bd5 = new BigDecimal("3");
System.out.println(bd4.divide(bd5));
Copy the code

Output result:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1690)
at BigDecimalTest.main(BigDecimalTest.java:38)
Copy the code

The number of digits after the decimal point should be set as follows, and rounded and rounded up/down or discarded:

System. The out. Println (bd4. Divide (bd5, 2, BigDecimal. ROUND_DOWN));Copy the code

The second parameter indicates the number of decimal places, and the third parameter indicates that the number of places exceeded is discarded (of course, you can also set the rounded up, etc.).

Do not compare sizes using BigDecimal’s Equals method, or you may end up comparing them differently than expected due to accuracy issues

BigDecimal bd1 = new BigDecimal("0"); BigDecimal bd2 = new BigDecimal("0.0"); System.out.println(bd1.equals(bd2)); System. Out.println (bd1. [compareTo] (http://javakk.com/tag/compareto "to view more about compareTo") (bd2) = = 0)Copy the code

Output result:

equals:false
compareTo:true
Copy the code

If you are not sure that your BigDecimal values have decimal cases, it is best to use compareTo!

Source: javakk.com/21.html