Java Double 精度丢失 不准确问题总结

来源:互联网 发布:json格式日志 编辑:程序博客网 时间:2024/06/05 21:49
  使用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); 



希望以上对大家有所帮助,如果说错了,还希望大家给点指正! 


分享到:  
JavaScript window.open 和 showModalDial ... | Java TreeMap 排序问题
  • 2009-07-05 11:22
  • 浏览 32534
  • 评论(7)
  • 相关推荐
评论
7 楼 mingyang2013 2013-01-28  
SereinChan 写道
楼主好厉害,收益了!
由于本人水平有点弱,所以想请教一下下面代码的含义:
BigDecimal bd1 = new BigDecimal(Double.toString(d1));

大概知道这语句的意思是调用 
BigDecimal的BigDecimal(String val)构造方法生成BigDecimal对象,但有点不是很明白Double.toString(d1)的意思,为什么可以直接写Double来调用toString方法,这个Double不需要new一下吗?


静态方法不需要new啦!
6 楼 小乌鸦 2012-06-12  
SereinChan 写道
楼主好厉害,收益了!
由于本人水平有点弱,所以想请教一下下面代码的含义:
BigDecimal bd1 = new BigDecimal(Double.toString(d1));

大概知道这语句的意思是调用 
BigDecimal的BigDecimal(String val)构造方法生成BigDecimal对象,但有点不是很明白Double.toString(d1)的意思,为什么可以直接写Double来调用toString方法,这个Double不需要new一下吗?


********
这是一个单例。。。
5 楼 SereinChan 2012-03-13  
楼主好厉害,收益了!
由于本人水平有点弱,所以想请教一下下面代码的含义:
BigDecimal bd1 = new BigDecimal(Double.toString(d1));

大概知道这语句的意思是调用 
BigDecimal的BigDecimal(String val)构造方法生成BigDecimal对象,但有点不是很明白Double.toString(d1)的意思,为什么可以直接写Double来调用toString方法,这个Double不需要new一下吗?
4 楼 all_wmh 2011-09-14  
System.out.println(new BigDecimal(Double.toString(712312312327.42325)));
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还是要缺失精度的!
3 楼 spiritfrog 2010-02-24  
zhaowei_520 写道
gary_zg 写道
楼主这种做法有问题,只要使用flaot或double,就会出现精度丢失
方法里的参数都是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类型去构造的,所以不会出现问题。
0 0