使用Java,double 进行运算时,经常出现精度丢失的问题,总是在一个正确的结果左右偏0.0000**1。 特别在实际项目中,通过一个公式校验该值是否大于0,如果大于0我们会做一件事情,小于0我们又处理其他事情。 这样的情况通过double计算出来的结果去和0比较大小,尤其是有小数点的时候,经常会因为精度丢失而导致程序处理流程出错。
所以一般对double类型进行运算时,做好对结果进行处理,然后拿这个值去做其他事情。
目前总结如下:
/**
* 对double数据进行取精度.
* @param value double数据.
* @param scale 精度位数(保留的小数位数).
* @param roundingMode 精度取值方式.
* @return 精度计算后的数据.
*/
public static double round(double value, int scale,
int roundingMode) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(scale, roundingMode);
double d = bd.doubleValue();
bd = null;
return d;
}
/**
* double 相加
* @param d1
* @param d2
* @return
*/
public double sum(double d1,double d2){
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.add(bd2).doubleValue();
}
/**
* double 相减
* @param d1
* @param d2
* @return
*/
public double sub(double d1,double d2){
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.subtract(bd2).doubleValue();
}
/**
* double 乘法
* @param d1
* @param d2
* @return
*/
public double mul(double d1,double d2){
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.multiply(bd2).doubleValue();
}
/**
* double 除法
* @param d1
* @param d2
* @param scale 四舍五入 小数点位数
* @return
*/
public double div(double d1,double d2,int scale){
// 当然在此之前,你要判断分母是否为0,
// 为0你可以根据实际需求做相应的处理
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.divide
(bd2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
这样,计算double类型的数据计算问题就可以处理了。
另外补充一下 JavaScript 四舍五入的方法:
小数点问题
Math.round(totalAmount*100)/100 (保留 2 位)
function formatFloat(src, pos)
{
return Math.round(src*Math.pow(10, pos))/Math.pow(10, pos);
}
希望以上对大家有所帮助,如果说错了,还希望大家给点指正!
所以一般对double类型进行运算时,做好对结果进行处理,然后拿这个值去做其他事情。
目前总结如下:
/**
* 对double数据进行取精度.
* @param value double数据.
* @param scale 精度位数(保留的小数位数).
* @param roundingMode 精度取值方式.
* @return 精度计算后的数据.
*/
public static double round(double value, int scale,
int roundingMode) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(scale, roundingMode);
double d = bd.doubleValue();
bd = null;
return d;
}
/**
* double 相加
* @param d1
* @param d2
* @return
*/
public double sum(double d1,double d2){
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.add(bd2).doubleValue();
}
/**
* double 相减
* @param d1
* @param d2
* @return
*/
public double sub(double d1,double d2){
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.subtract(bd2).doubleValue();
}
/**
* double 乘法
* @param d1
* @param d2
* @return
*/
public double mul(double d1,double d2){
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.multiply(bd2).doubleValue();
}
/**
* double 除法
* @param d1
* @param d2
* @param scale 四舍五入 小数点位数
* @return
*/
public double div(double d1,double d2,int scale){
// 当然在此之前,你要判断分母是否为0,
// 为0你可以根据实际需求做相应的处理
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.divide
(bd2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
这样,计算double类型的数据计算问题就可以处理了。
另外补充一下 JavaScript 四舍五入的方法:
小数点问题
Math.round(totalAmount*100)/100 (保留 2 位)
function formatFloat(src, pos)
{
return Math.round(src*Math.pow(10, pos))/Math.pow(10, pos);
}
希望以上对大家有所帮助,如果说错了,还希望大家给点指正!
评论
由于本人水平有点弱,所以想请教一下下面代码的含义:
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
大概知道这语句的意思是调用
BigDecimal的BigDecimal(String val)构造方法生成BigDecimal对象,但有点不是很明白Double.toString(d1)的意思,为什么可以直接写Double来调用toString方法,这个Double不需要new一下吗?
静态方法不需要new啦!
由于本人水平有点弱,所以想请教一下下面代码的含义:
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
大概知道这语句的意思是调用
BigDecimal的BigDecimal(String val)构造方法生成BigDecimal对象,但有点不是很明白Double.toString(d1)的意思,为什么可以直接写Double来调用toString方法,这个Double不需要new一下吗?
********
这是一个单例。。。
由于本人水平有点弱,所以想请教一下下面代码的含义:
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
大概知道这语句的意思是调用
BigDecimal的BigDecimal(String val)构造方法生成BigDecimal对象,但有点不是很明白Double.toString(d1)的意思,为什么可以直接写Double来调用toString方法,这个Double不需要new一下吗?
System.out.println(new BigDecimal(Double.toString(712312312327.42326)));
System.out.println(new BigDecimal(Double.toString(712312312327.42327)));
System.out.println(new BigDecimal(Double.toString(712312312327.42328)));
楼主你可以试试这个就知道toString还是要缺失精度的!
方法里的参数都是double,在new BigDecimal前,double值就已经出现精度丢失了
BigDecimal 有两个构造:
1. BigDecimal(double val)
2. BigDecimal(String val)
但如果使用 double 构造,API中已经说明,这个构造器的结果可能会有不可预知的结果。如: System.out.println(new BigDecimal(1.2));
结果是:1.1999999999999999555910790149937383830547332763671875
而并非我们认为的 1.2;
所以再构造BigDecimal的时候,原则上我们使用 BigDecimal(String val)构造,这样就不会出问题,而我提供的方法中(当然也是借鉴了网上的资料),都是把Double类型转换成String类型去构造的,所以不会出现问题。