Java中不同数值类型间转换与计算精度丢失问题

版权声明:本文为博主原创文章,转载需声明出处。 https://blog.csdn.net/gulingfengze/article/details/54094193

在Java编程过程中,经常会涉及到不同数值类型之间的计算问题,例如:

int m=6;  
float n=3.5f;  
double p=2.75d;
System.out.println(m + n); 
System.out.println(n + p);

运行程序,输出结果分别为:9.5和6.25。计算机在执行m+n的时候,首先会将m先转换成float类型,然后再将其与n进行加法运算。同理,执行n+p时,首先将n转换成double类型,然后再将其与p进行加法运算。下面我们来看一下实际编码过程中出现的问题:

我们可以看出,当两个不同类型的数进行基本运算符操作时,精度小的数值类型首先会向精度大的数值类型进行转换,最后进行计算。下面来看下数值类型之间的合法转换图。

数值类型之间的合法转换图

图中的实线箭头表示有信息丢失的转换,虚线箭头表示无信息丢失的转换。其转换规则如下:

  • 如果两个操作数中有一个是double类型,另一个就会转换为double类型;
  • 否则,如果有一个操作数是float,另一个就会转化为float;
  • 否则,如果有一个操作数是long,另一个就会转换为long;
  • 否则,两个操作数都将转换为int类型。

    为了理解这些规则,这里再举几个例子:

public class MyJava {

    /**
     * @param args
     */
    public static void main(String[] args) {
        int a=6;  
        float b=3.5f;  
        double c =5.26d;
        long d=82l;   
        short e=2;  
        byte f=3; 
        System.out.println(a + b);
        System.out.println(a + c);
        System.out.println(a + d);
        System.out.println(a + e);
        System.out.println(a + f);
        System.out.println(b + c);
        System.out.println(b + d);
        System.out.println(b + e);
        System.out.println(b + f);
        System.out.println(c + d);
        System.out.println(c + e);
        System.out.println(c + f);
        System.out.println(d + e);
        System.out.println(d + f);
        System.out.println(e + f);
    }

}

输出结果为:

9.5
11.26
88
8
9
8.76
85.5
5.5
6.5
87.26
7.26
8.26
84
85
5

接下来我们再看下数值之间计算时候存在的计算精度丢失问题。例子如下所示:

public class MyJava {

    /**
     * @param args
     */
    public static void main(String[] args) {
        int a = 3;
        double b = 0.03;
        double c = 0.03;
        double d = a+b+c;
        System.out.println("d:" + d); 
    }

} 

输出结果为:

d:3.0599999999999996

这里我们可以看到最后的结果并不是我们预期的那样为3.06,其实double类型数值的计算经常会出现这种精度丢失的问题,尤其是有小数点的情况下,常常会应为精度丢失而导致程序出错。那么该如何解决这个问题呢?这时候我们需要使用位于java.math包中的BigDecima类并用String来构造。具体使用方法如下:

    /** 
     * @param m1 
     * @param m2 
     * @return 
     */ 
    public static double add(double m1, double m2) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.add(p2).doubleValue();
    }

    /** 
     * @param m1 
     * @param m2 
     * @return 
     */ 
    public static double sub(double m1, double m2) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.subtract(p2).doubleValue();
    }

    /** 
     * @param m1 
     * @param m2 
     * @return 
     */ 
    public static double mul(double m1, double m2) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.multiply(p2).doubleValue();
    }


     /**    
      *   @param   m1  
      *   @param   m2        
      *   @param   scale      
      *   @return     
      */     
    public static double div(double m1, double m2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("Parameter error");
        }
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        return p1.divide(p2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    } 

以上就是问题的处理方法了。

猜你喜欢

转载自blog.csdn.net/gulingfengze/article/details/54094193
今日推荐