5分钟彻底搞懂浮点数精度丢失问题

北京中科 https://yyk.familydoctor.com.cn/2831/detail/

我们在平时的编程工作中,会经常接触到“浮点数精度丢失”问题。(如果你目前还没有遇到过,只能说明你代码写的还是太少啦,该加油啦^_^)一般的业务系统,“浮点数精度丢失”问题所导致的后果可能在业务可接受的范围,所以并没有起很多程序员的重视;但是对于健壮性要求较强(比如,金融或财务系统),精度丢失所引起的后果就会是灾难性的,程序员离跑路已经不远了~~。通过本文知识,让我们花5分钟时间彻底搞懂它,相信聪明的你,看完一定会有收获!

从一个经典例子谈起:

js语言示例:varf1=0.1;varf2=0.2;consol.log(f1+f2);//您认为结果是0.3?真实结果是0.java语言示例:

publicstaticvoidmain(String[]args){doubld1=0.1;doubld2=0.2;Systm.out.println(d1+d2);//您认为结果是0.3?真实结果是:0.}

上述两个算数的和,为什么不是0.3呢?就是因为“浮点数精度丢失”问题造成的。

“浮点数精度丢失”问题产生的原因

根本原因

:0.1这个十进制小数并不能很好的被二进制表示.

为什么0.1不能被二进制表示呢?

十进制小数转二进制的算法是:整数部分:除2取余,直到商数为0,结果逆序排列;小数部分:乘2取整,直到小数部分乘积积为0,结果顺序排列;以0.为例演示如下:0.×2=0.25.......................00.25×2=0.5.......................00.5×2=1.0.......................1即十进制的0.,表示成二进制为0.现在来看十进制的0.1转二进制:0.1×2=0.2.....................00.2×2=0.4.....................00.4×2=0.8.....................00.8×2=1.6......................10.6×2=1.2......................10.2×2=0.4......................0

........

聪明的你,应该已经发现了,这个算法过程是无限循环的,因此可以得出结论:浮点数的小数部分会有精度丢失问题

“浮点数精度丢失”问题的解决

具体解决方案,跟具体业务场景(上下文)有一定的关系。

(因为不同的解决方案,对应的成本不同,毕竟,这个世界上本就不存在“放之四海而皆准”的真理啊^_^)

下面给出两个经典场景及其解决方案,以飨读者。场景1:浮点数比较

解决方案:

比较两个浮点数是否相等,需要通过两者之差的绝对值是否小于某个阈值来判断。

举例如下:(以js语言为例):consol.log(1/3==(1-2/3));//falsconsol.log(Math.abs(1/3-(1-2/3))0.0000);//tru场景2:金融/财务模块的金额或费用计算解决方案:

熙熙攘攘,皆为利往。钱实在是太重要了,少一分都不能承受之重之痛。所以,对于金额或费用字段,直接弃用float或doublu吧,老老实实全部都用BigDcimal数据类型吧

注:BigDcimal型本身提供体验独立的加减乘除代数运算方法(底层是基于String,所以不会有精度丢失问题)

--------------------------------十年技术沉淀,只做原创文章;及时


转载请注明:http://www.aierlanlan.com/cyrz/3082.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了