Initialize BigDecimal with type String

Java provides an API class, BigDecimal, in the java.math package to perform precise operations on numbers that are more than 16 significant bits. When bigDecimal is initialized, do not pass in a value of type double or float to the constructor. By comparison, test2 still has precision problems, whereas bigDecimal objects that take strings do not

// Use the String construct
BigDecimal b1 = new BigDecimal("0.1");
// Or:
BigDecimal b1 = BigDecimal.valueOf(0.1);
// Open the source code for valueOf and see that the source code also uses new BigDecimal(String); Returns the value of a BigDecimal object
// The following code is available:
public static BigDecimal valueOf(double val) {
    Reminder: A zero double returns '0.0', so we cannot fastpath
    // to use the constant ZERO. This might be important enough to
    // justify a factory approach, a cache, or a few private
    // constants, later.
    return new BigDecimal(Double.toString(val));
}
Copy the code

Do not use equals when comparing BigDecimal values

The equals comparison compares the size of the value to the size of the precision, i.e. 0.00 and 0.000 are not equal, and compareTo() is used to do the comparison.

Ensure that the value involved in the calculation cannot be NULL

When using BigDecimal type to calculate, addition, subtraction, multiplication, division, comparison, make sure to participate in the calculation of two values cannot be empty, otherwise it will throw the Java. Lang. NullPointerException.

For example, the following two pieces of code will both throw exceptions:

BigDecimal number1 = null;
BigDecimal number2 = new BigDecimal("11.12");

BigDecimal number3 = number1.add(number2);
System.out.println("number1 add number2 = " + number3);

BigDecimal number1 = new BigDecimal("88.88");
BigDecimal number2 = null;

BigDecimal number3 = number1.add(number2);
System.out.println("number1 add number2 = " + number3);
Copy the code

The exception thrown is shown below:

usedivideBe careful when using infinite repeating decimals and divisor

When using BigDecimal divide method at a time, throw Java. Lang. ArithmeticException abnormalities, the error code is as follows:

// Tax inclusive
BigDecimal inclusiveTaxAmount = new BigDecimal("1000");
/ / rate
BigDecimal taxRate = new BigDecimal("0.13");
// Amount excluding tax = Amount including tax/(1+ tax rate)
BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate));

System.out.println(exclusiveTaxAmount);
Copy the code

The runtime throws the following exception:

This error occurs because divisible is not divisible, resulting in an infinite repeating decimal:

The solution is to specify rounding patterns, such as the rounding pattern we use most often:

// Amount excluding tax = Amount including tax/(1+ tax rate)
BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate),RoundingMode.HALF_UP);
Copy the code

In this case, no error is reported, and the output is 885

But here I want to keep 2 decimal places and round them off, so the code should look like this:

// Amount excluding tax = Amount including tax/(1+ tax rate)
BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate), 2, RoundingMode.HALF_UP);
Copy the code

The output is 884.96

BigDecimal to String, scientific notation problem

Conclusion: to convert BigDecimal toString, it is recommended to use toPlainString() instead of toString()

Maybe you could write it like this:

BigDecimal amount = new BigDecimal("3450.67");
System.out.println(amount.toString());
Copy the code

Output result: 3450.67

In most cases this is fine, but in some cases it can be easy to pothole, as in the following three examples:

System.out.println( new BigDecimal("0.000000000000").toString());
// The output is 0E-12

BigDecimal bigDecimal = new BigDecimal("1E+11");
System.out.println(bigDecimal.toString());
// Output: 1E+11
Copy the code

A more common scenario is zeroing, which is also easy to stomp on, such as the code shown below, which is expected to output 3550, but is not:

BigDecimal bigDecimal = new BigDecimal("3550.00");
System.out.println(bigDecimal.stripTrailingZeros().toString());
// result: 3.55E+3

// Use the toPlainString() method to avoid this problem, as follows:
System.out.println( new BigDecimal("0.000000000000").toPlainString());
System.out.println( new BigDecimal("1E+11").toPlainString());
System.out.println(new BigDecimal("3550.00").stripTrailingZeros().toPlainString());

// Output result:
/ / 0.000000000000
/ / 100000000000
/ / 3550
Copy the code

In fact, BigDecimal provides three methods to convert to String:

  1. ToString () uses scientific notation in some scenarios

  2. ToPlainString () does not use any notation

  3. ToEngineeringString () uses engineering notation in some scenarios

Here are the differences between scientific notation and engineering notation:

Scientific notation is the representation of numbers as multiples of 10.

Engineering notation, on the basis of scientific notation, limits the power of 10 to multiples of 3.

For example:

The original value Science and technology law Engineering counting method
2700 2.7 x 10 after 2.7 x 10 after
27000 2.7 x 10 ⁴ 27 after 10 x
270000 2.7 x 10 ⁵ 10 after 270 x
2700000 2.7 x 10 ⁶ 2.7 x 10 ⁶

Sample code:

BigDecimal bigDecimal = new BigDecimal("270000.00").stripTrailingZeros();
System.out.println(bigDecimal.toString());
System.out.println(bigDecimal.toPlainString());
System.out.println(bigDecimal.toEngineeringString());

// Output result:
/ / 2.7 e+5
/ / 270000
//270E+3
Copy the code

Use standard

Try not to use New BigDecimal(“0”) in your project, and instead use the constant bigDecimal.zero provided by BigDecimal.

BigDecimal zero = BigDecimal.ZERO;
BigDecimal one = BigDecimal.ONE;
BigDecimal ten = BigDecimal.TEN;
Copy the code