浮点数精度丢失

探讨了浮点数在计算机中因二进制转换而导致的运算误差问题,特别是使用float和double类型时的常见误区。文章介绍了精度丢失的原因,并提出使用BigDecimal或long类型作为替代方案,以确保高精度计算。

首先考虑一下下面的输出值 ,是否和你想的一样??

 

 

产生原因:首先计算机进行的是二进制运算,我们输入的十进制数字会先转换成二进制,进行运算后再转换为十进制输出。Float和Double提供了快速的运算,然而问题在于转换为二进制的时候,有些数字不能完全转换,只能无限接近于原本的值(类似于十进制的1/3),这就导致了在后来的运算会出现不正确结果的情况。

 

浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。往往产生误差不是 因为数的大小,而是因为数的精度。因此,产生的结果接近但不等于想要的结果。尤其在使用 float 和 double 作精确运 算的时候要特别小心。
可以考虑采用一些替代方案来实现。如通过 String 结合 BigDecimal 或 者通过使用 long 类型来转换。

使用BigDecimal解决精度丢失问题:

BigDecimal b1 = new BigDecimal("0.05");
BigDecimal b2 = new BigDecimal("0.01");
System.out.println(b1.add(b2)); // 求和

 

 

浮点数精度丢失是计算机编程中的一个常见问题。浮点数由阶码和尾数两部分组成,默认保存为 double 类型,float 的十进制精度为 7 位,double 的十进制精度为 16 位,在计算机中存储时,由于内存空间有限(如 32 位),必须“截断”无法精确表示的部分,所以可能出现精度丢失问题 [^2][^4]。 从原理上来说,小数的二进制表示有时不能精确。就像十进制系统中不能准确表示 1/3 一样,二进制也无法准确表示 1/10,这是浮点型出现精度丢失问题的主要原因 [^3]。 在实际编程中,有很多浮点数精度丢失的经典案例。例如在 Java 中: ```java public class BigDecimalTest { public static void main(String[] args) { float f1 = 0.9f; float f2 = 0.8f; float f3 = 1.1f; float f4 = 1.0f; float f5 = f1 - f2; float f6 = f3 - f4; System.out.println(f5 - f6); } } ``` 此代码运行结果为 `-5.9604645E-8`,体现了浮点数精度丢失 [^1]。 在 C++ 中也有类似情况: ```c #include <stdio.h> int main() { // 直接比较(会输出0,即False) printf("0.1 + 0.2 == 0.3 => %d\n", 0.1 + 0.2 == 0.3); // 打印实际计算结果 printf("0.1 + 0.2 = %.17g\n", 0.1 + 0.2); return 0; } ``` 代码中 `0.1 + 0.2 == 0.3` 比较结果为 `False`,也说明了浮点数精度丢失问题 [^4]。 为了解决浮点数精度丢失问题,可使用高精度计算库,如 Java 中的 BigDecimal 类,它可以精确表示和计算浮点数。示例代码如下: ```java 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); } } ``` 通过使用 BigDecimal 类可以避免浮点数精度丢失带来的问题 [^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值