目录
一、浮点数精度丢失的概念
当某些十进制小数在二进制中是无限循环小数时,计算机在存储和处理这些小数时,由于存储位数的限制,无法精确表示它们,这就会导致浮点数精度丢失。
二、以0.1为例的二进制转换过程
-
对于十进制小数 0.1,将其转换为二进制的过程如下:
-
0.1 * 2 = 0.2,取整数部分 0
-
0.2 * 2 = 0.4,取整数部分 0
-
0.4 * 2 = 0.8,取整数部分 0
-
0.8 * 2 = 1.6,取整数部分 1
-
0.6 * 2 = 1.2,取整数部分 1
-
0.2 * 2 = 0.4,取整数部分 0(开始循环)
-
0.4 * 2 = 0.8,取整数部分 0
-
0.8 * 2 = 1.6,取整数部分 1
-
0.6 * 2 = 1.2,取整数部分 1
-
以此类推,会形成一个无限循环的二进制小数:0.0001100110011...
-
三、存储精度限制导致的问题
计算机存储浮点数时,使用有限的位数(如 float
是 32 位,double
是 64 位)。
对于 float
类型,它使用 23 位存储尾数,对于 double
类型,使用 52 位存储尾数。
由于存储位数有限,无法精确存储无限循环的二进制小数,因此会截断二进制表示,导致精度丢失。
四、设置精度避免无限循环与精度丢失的关系
在将十进制小数转换为二进制时设置精度,是为了在转换过程中避免无限循环的计算,但这并不能完全解决浮点数精度丢失的问题。
精度丢失主要是由于存储浮点数的有限位数造成的,而不是仅仅在转换过程中设置精度就能解决的。
五、解决和缓解精度丢失的方法
使用高精度计算库:如 Java 中的 BigDecimal
类,可以精确表示和计算浮点数。
import java.math.BigDecimal;
public class BigDecimalExample {
public static void main(String[] args) {
// 基本类型会产生“精度丢失”问题
double x = 10 - 9.9;
double y = 1 - 9.0 / 10;
System.out.println("10 - 9.9 = "+ x);
System.out.println("1 - 9.0 ÷ 10 = "+ y);
// double x = 10 - 9.9
System.out.println("解决:double x = 10 - 9.9 的精度丢失问题。");
BigDecimal dec1 = new BigDecimal("10");
BigDecimal dec2 = new BigDecimal("9.9");
BigDecimal decx = dec1.subtract(dec2);
System.out.printf("%.1f - %.1f = %.1f\n",dec1,dec2,decx);
// double y = 1 - 9.0 / 10
System.out.println("解决:double y = 1 - 9.0 / 10 的精度丢失问题。");
BigDecimal dec3 = new BigDecimal("1.0");
BigDecimal dec4 = new BigDecimal("9.0");
BigDecimal dec5 = new BigDecimal("10");
BigDecimal decy = dec3.subtract(dec4.divide(dec5));
System.out.printf("%.1f - %.1f ÷ %.1f = %.1f\n",dec3,dec4,dec5,decy);
}
}
运行结果:
六、总结
某些十进制小数在二进制中是无限循环小数,如 0.1,会导致存储和计算时的精度丢失。
设置转换时的精度只能避免无限循环的计算,但无法解决存储位数有限导致的精度丢失。
使用高精度计算库(如 BigDecimal
)可以缓解浮点数的精度丢失问题。
总之,浮点数精度丢失是由于存储位数有限导致的,在涉及精确计算时,需要考虑使用高精度数据类型或计算库,而不是仅仅依靠设置转换精度
标签:10,存储,BigDecimal,浮点数,丢失,精度 From: https://blog.csdn.net/CSDN_xysf/article/details/145246870