在Java中直接对浮点数进行加减乘除运算时会出现精度丢失的问题,如下:
public class Test {
public static void main(String[] args) {
System.out.println(0.06+0.01);
System.out.println(2.0-1.1);
System.out.println(3.3*3);
System.out.println(3.3/3);
}
}
实际的运行结果如下:
0.06999999999999999
0.8999999999999999
9.899999999999999
1.0999999999999999
实际上计算机是二进制的,而浮点数无法通过二进制精确的表示。
浮点数在我们计算机中存储包括三个部分(浮点数的存储请自行百度):
1、符号位(Sign) : 0代表正,1代表为负。
2、指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储。
3、尾数部分(Mantissa):尾数部分。
因此浮点数在计算的时候有时会产生一定的误差,在实际项目中可能需要精确的计算,java中一般采用java.math.BigDecimal类来进行精确的计算。
以下是借用java.math.BigDecimal类来实现double类型数据的加减乘除运算的工具类:
import java.math.BigDecimal;
/**
* Double类型数据运算工具类(提供精确运算的加减乘除方法)
* @author
*
*/
public class DoubleArithUtil {
/**
* 加法运算
* @param x 被加数
* @param y 加数
* @return 两数的和
*/
public static double add(double x, double y) {
BigDecimal vala = new BigDecimal(Double.toString(x));
BigDecimal valb = new BigDecimal(Double.toString(y));
return vala.add(valb).doubleValue();
}
/**
* 减法运算
* @param x 被减数
* @param y 减数
* @return 两数的差
*/
public static double subtract(double x, double y) {
BigDecimal vala = new BigDecimal(Double.toString(x));
BigDecimal valb = new BigDecimal(Double.toString(y));
return vala.subtract(valb).doubleValue();
}
/**
* 乘法运算
* @param x 被乘数
* @param y 乘数
* @return 两数的积
*/
public static double multiply(double x, double y) {
BigDecimal vala = new BigDecimal(Double.toString(x));
BigDecimal valb = new BigDecimal(Double.toString(y));
return vala.multiply(valb).doubleValue();
}
/**
* 除法运算(结果进行四舍五入)
* @param x 被除数
* @param y 除数
* @param scale 小数精确位数
* @return 两数的商
* @throws ArithmeticException
*/
public static double divide(double x, double y, int scale) throws ArithmeticException {
if (scale < 0) {
throw new ArithmeticException("精确度不能小于0");
}
BigDecimal vala = new BigDecimal(Double.toString(x));
BigDecimal valb = new BigDecimal(Double.toString(y));
return vala.divide(valb, scale, BigDecimal.ROUND_HALF_EVEN).doubleValue();
}
}