BigDecimal is used in Java for exact calculations

  • 2020-06-12 09:04:36
  • OfStack

Let's start with the following code example:


public class Test_1 {
  public static void main(String[] args) {
    System.out.println(0.06+0.01);
    System.out.println(1.0-0.42);
    System.out.println(4.015*100);
    System.out.println(303.1/1000);
  }
}

The results of the run are as follows.

0.06999999999999999

0.5800000000000001

401.49999999999994

0.30310000000000004

You think you're wrong, but it turns out this is it. What's the problem? The reason is that our computer is base 2. Floating point Numbers are not exactly represented in base 2. Our CPU representation of floating point Numbers consists of two parts: exponent and mantissa, such a representation will generally lose the accuracy of 1 definite, and some floating point operations will also produce 1 definite error. For example, the base 2 representation of 2.4 is not the exact 2.4. Instead, the closest binary representation is 2.39999999999999. The value of a floating point number is actually calculated by a specific mathematical formula.

In fact, float of java can only be used for scientific or engineering calculations. In most business calculations, the java.math.BigDecimal class is generally used for precise calculations.

When using BigDecimal class for calculation, it is mainly divided into the following steps:

1. Use float or double variables to build BigDecimal objects.

2. Carry out arithmetic operation by calling the corresponding methods of addition, subtraction, multiplication and division of BigDecimal.

3. Convert BigDecimal objects to float, double, int, etc.

In general, you can use the BigDecimal constructor or the static valueOf() method to build primitives into BigDecimal objects.


 BigDecimal b1 = new BigDecimal(Double.toString(0.48));
BigDecimal b2 = BigDecimal.valueOf(0.48);

The BigDecimal class provides member methods for common addition, subtraction, multiplication, and division.


 public BigDecimal add(BigDecimal value);            // add 
 public BigDecimal subtract(BigDecimal value);          // subtraction  
 public BigDecimal multiply(BigDecimal value);          // The multiplication 
 public BigDecimal divide(BigDecimal value);           // division 

After the corresponding calculation, we may need to convert the BigDecimal object into a variable of the corresponding basic data type, using methods such as floatValue(), doubleValue(), etc.

Below is a utility class that provides add, subtract, multiply, and divide operations.


public class Arith {
  /**
   *  Provides accurate addition calculation add methods 
   * @param value1  augend 
   * @param value2  addend 
   * @return  The sum of two parameters 
   */
  public static double add(double value1,double value2){
    BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
    BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
    return b1.add(b2).doubleValue();
  }
  /**
   *  Provides accurate subtraction operations sub methods 
   * @param value1  minuend 
   * @param value2  reduction 
   * @return  The difference between the two parameters 
   */
  public static double sub(double value1,double value2){
    BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
    BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
    return b1.subtract(b2).doubleValue();
  }
  /**
   *  Provides accurate multiplication mul methods 
   * @param value1  multiplicand 
   * @param value2  The multiplier 
   * @return  The product of two parameters 
   */
  public static double mul(double value1,double value2){
    BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
    BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
    return b1.multiply(b2).doubleValue();
  }
  /**
   *  Provides an accurate division method div
   * @param value1  dividend 
   * @param value2  divisor 
   * @param scale  Precise range 
   * @return  The quotient of two parameters 
   * @throws IllegalAccessException
   */
  public static double div(double value1,double value2,int scale) throws IllegalAccessException{
    // If the exact range is less than 0 , throws an exception message 
    if(scale<0){     
      throw new IllegalAccessException(" Accuracy cannot be less than 0");
    }
    BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
    BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
    return b1.divide(b2, scale).doubleValue();  
  }
}

Related articles: