版权声明:本文为博主原创文章,转载需声明出处。 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();
}
以上就是问题的处理方法了。