Home > Article > Computer Tutorials > How to deal with double precision issues in JAVA
public static double add(double d1,double d2){
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.add(b2).doubleValue();
}
public static double sub(double d1,double d2){
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.subtract(b2).doubleValue();
}
public static double mul(double d1,double d2){
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.multiply(b2).doubleValue();
}
public static double div(double d1,double d2){
return div(d1,d2,DEF_DIV_SCALE);
}
public static double div(double d1,double d2,int scale){
//scale is the number of digits to be retained after the decimal point
if(scalethrow new IllegalArgumentException ("precision cannot be less than zero");
}
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
Call these methods when used.
In most cases, the results calculated using double and float are accurate, but in some systems that require high precision, this problem is very serious.
A principle mentioned in "Effective Java" is that float and double can only be used for scientific calculations or engineering calculations, but in commercial calculations we have to use java.math.BigDecimal. By using the BigDecimal class To solve the above problems, the example code is as follows:
package ex;
import java.math.*;
public class BigDecimalDemo {
public static void main(String[] args){
System.out.println(ArithUtil.add(0.01, 0.05));
System.out.println(ArithUtil.sub(1.0, 0.42));
System.out.println(ArithUtil.mul(4.015, 100));
System.out.println(ArithUtil.div(123.3, 100));
}
}
class ArithUtil{
private static final int DEF_DIV_SCALE=10;
private ArithUtil(){}
//Add
public static double add(double d1,double d2){
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.add(b2).doubleValue();
}
//Subtraction
public static double sub(double d1,double d2){
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.subtract(b2).doubleValue();
}
//Multiply
public static double mul(double d1,double d2){
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.multiply(b2).doubleValue();
}
//Division
public static double div(double d1,double d2){
return div(d1,d2,DEF_DIV_SCALE);
}
public static double div(double d1,double d2,int scale){
if(scale
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
When two int values are divided, the result is int, and the value obtained is directly removed from the decimal part.
if:
int i=1;j=3;i/j==0 returns true
Similarly, i/3==0 1/3==0 1/j==0 all return true
If double res=i/j, the result returned will not be 0.333..., but 0
If you want to get 0.333..., you need res=((double)i)/j;
And yours
fReuslt=(int)((double)num1/num2)
Num1/num2 will be executed first. If num1 and num2 are both int, the result will eventually be int. Assume here that num1=6, num2=5, then num1/num2==1 is true, not 1.2 , then, execute (double) res again, res here is num1/num2, so res=1, so after double, it is still 1, not 1.2
The above is the detailed content of How to deal with double precision issues in JAVA. For more information, please follow other related articles on the PHP Chinese website!