黑马程序员技术交流社区

标题: 我今天在做联系时遇到的一个问题 [打印本页]

作者: 丁朋    时间: 2012-7-16 10:33
标题: 我今天在做联系时遇到的一个问题
今天在做练习时遇到了一个很奇怪的事,
class  lianxi
{
public static void main(String[] args)
{
  System.out.println(9.8-8.8);//打印正常
  System.out.println(9.9-8.8);//打印不正常
}
}

打印结果为什么失真
1.0
1.0999999999999996

作者: 全海波    时间: 2012-7-16 10:42
学过计算机组成原理的话,你应该就会知道,这个是浮点数的问题
作者: 何旭栋    时间: 2012-7-16 11:00
且看看float数据类型的存储结构:
float占用4个字节,也就是32为二进制码,分别是:
符号位:1位(31),表示float的正负,0为正,1为负
幂指数:8位(23-30),表示2进制权的幂次
有效位:23位(0-22),表示有效数字

因为浮点数在系统中使用的是二进制的科学计数法,浮点运算有误差。
作者: 孙新强    时间: 2012-7-16 11:02
在java中,使用double进行运算,有时会出现精度丢失的问题,值会有那么0.00000***1偏差的偏差,导致匹配校验常常出现问题
解决方案如下:
  /**  
     * 对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类型的数据计算问题就可以处理了。


作者: 余清兰    时间: 2012-7-16 11:02
楼上的说得对,计算机计算整型的精度比较高,编译器编译的时候浮点型数据可能会丢失,8.8可能变成8.7999999
java的API的java.math包里提供了一个BigDecimal类,该类里有个方法subtract方法可以解决此问题,具体的你可以查阅API文档
作者: 侯茂绵    时间: 2012-7-16 16:03
这跟浮点数数精确度有关
2次运算结果不同 是因为浮点数精确度损失





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2