The solution to the abnormal result of java type operation

  • 2020-05-24 05:37:39
  • OfStack

Question:

Operating on two values of type double sometimes results in outlier values. Such as:


System.out.println(19.99+20);
  System.out.println(1.0-0.66);
  System.out.println(0.033*100);
  System.out.println(12.3/100);

Output:

39.989999999999995
0.33999999999999997
3.3000000000000003
0.12300000000000001

Solutions:

The simple floating point types float and double in Java are not capable of performing operations because they are normal most of the time, but occasionally present the problems shown above. The problem is not bug of JAVA, because the computer itself is in base 2, and floating point Numbers are actually only approximations, so when converting from base 2 to 10 floating point Numbers, the accuracy is easily lost, resulting in a drop in precision.

To ensure accuracy, use the BigDecimal class, and instead of directly transferring double to BigDecimal, transfer double to string to BigDecimal. That is, you cannot use the BigDecimal(double val) method and you will find no effect. Use the BigDecimal(String val) method. Specific examples are shown below.

Example of operation for double type 4:

1, add


public static double add(double a1, double b1) { 
   BigDecimal a2 = new BigDecimal(Double.toString(a1)); 
   BigDecimal b2 = new BigDecimal(Double.toString(b1)); 
   return a2.add(b2).doubleValue(); 
  }

2, by subtracting


public static double sub(double a1, double b1) { 
   BigDecimal a2 = new BigDecimal(Double.toString(a1)); 
   BigDecimal b2 = new BigDecimal(Double.toString(b1)); 
   return a2.subtract(b2).doubleValue(); 
  }

3, multiply


public static double mul(double a1, double b1) { 
   BigDecimal a2 = new BigDecimal(Double.toString(a1)); 
   BigDecimal b2 = new BigDecimal(Double.toString(b1)); 
   return a2.multiply(b2).doubleValue(); 
  }

4, deduct


public static double div(double a1, double b1, int scale) {
  if (scale < 0) { 
   throw new IllegalArgumentException("error"); 
  }
  BigDecimal a2 = new BigDecimal(Double.toString(a1)); 
  BigDecimal b2 = new BigDecimal(Double.toString(b1)); 
  return a2.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); 
 }

Precision is specified when the scale parameter is not infinite.


Related articles: