Java中double或float运算丢失精度问题

Java中double或float运算丢失精度问题

计算机内部是用的是二进制码,当输入float或者double类型的十进制数进行运算的时候,会先转化成二进制数再进行运算,最后在转化为十进制输出。然而有些数字不能完全转化成二进制,计算机只能将结果无限趋近于原本十进制的数值,故会出现精度丢失的问题。

举例:

public static void main(String[] args) {
	double a = 0.05;
	double b = 0.07;
	double c = a+b;
	System.out.println(c);
	float x = 0.05f;
	float y = 0.07f;
	float z = x+y;
	System.out.println(z);
}

输出: 进制转化分为整数部分和小数部分,对于整数部分相信很多人都很清楚,小数部分则稍微麻烦一些,java中只提供了整数的进制转化代码。下面的链接和二维码是一篇关于二进制、八进制、十进制、十六进制之间转换的博客,比较详细。 十进制转换为二进制小数部分采用“乘二取整”,十进制0.05转换为二进制为0.00001100110011001100110011001100110011001100110011001101(保留56位小数);

十进制0.07转换为二进制为0.00010001111010111000010100011110101110000101000111101100(保留56位小数);

再将二进制相加,计算时先把两个二进制数对齐(以小数点对齐),1+1=10,此时向上一位进1,0写在本位,计算方式如下图所示: 结果为0.00011110101110000101000111101011100001010001111010111001。

最后将二进制转换为十进制得到0.12000000000000001,看似简单,实则暗藏玄机啊。

对于double或float计算可以采用BigDecimal类,如下:

public static void main(String[] args) {
	double a = 0.05;
	double b = 0.07;
	double c = Double.valueOf(BigDecimal.valueOf(a).add(BigDecimal.valueOf(b)).toString());
	System.out.println(c);
	float x = 0.05f;
	float y = 0.07f;
	float z = Float.valueOf(BigDecimal.valueOf(x).add(BigDecimal.valueOf(y)).toString());
	System.out.println(z);
}
经验分享 程序员 微信小程序 职场和发展