0.1+0.2==0.3?


  刚刚在逛Stack的时候,看见有人在问Java下的一个浮点数运算的问题,这个问题我之前也碰到过,不过项目中遇见的比较少,就忘记了。想想还是做个笔记,记录一下,以供后续温习。

有趣的小例子

  先做一道算术题0.1+0.2=?,也许你想都不用想就回答等于0.3,那么在计算机中是如何表现的呢?测试如下:

var a = 0.1 + 0.2;
var b = 0.3;
Console.WriteLine(a);
Console.WriteLine(a == b);

输出结果是:0.3和False,0.3!=0.3?且不说为什么,再测试一段:

float a = 0.7f;
float b = 0.6f;
Console.WriteLine(a - b);

输出结果是:0.09999996,不等于0.1,我的机器抽风了?再试试: 

float a = 0.75f;
float b = 0.25f;
Console.WriteLine(a - b);

输出结果是:0.5,居然又正常了,顿时对C#有了一股深深的怨念,这点小事儿你都办不好,不过想想那些大神的能力肯定甩我几十条街,不会犯这种低级错误,还是看看为什么吧。

分析

  究其根本,还是因为计算机采用二进制来表示十进制数据,C#中采用IEEE754标准来存储浮点格式,单精度的浮点格式分为1位符号位、8位偏置指数位、23位小数位,通常,我们将十进制转换为二进制需要进行如下操作:

  将浮点型数据分为整数部分和小数部分,整数部分除2取余,得到的商再除以2取余,直到商等于0为止,然后把得到余数反序排列,就得到了整数部分;小数部分用乘2法不断将整数部分取出,知道小数中的部分为0或者达到精度时为止。以4.25为例:

  整数位:4

  4/2=2                  0

  2/2=1                  0

  1/2=0                  1

  将001反序得到100即整数位4

  小数位:0.25

  0.25*2=0.5          0

  0.5*2=1.0            1

  01即表示0.25

可是当小数位为0.6时,推算如下:

  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.2*2=0.4            0

  0.4*2=0.8            0

  0.8*2=1.6            1

  ......

如此循环往复,很明显23位是无法完全表述0.6这个小数的,这也就导致了上诉异常的产生。

  .NET中提供了decimal来解决这个问题,但decimal也是浮点数类型,只是精度更高,仍然有精度损失存在,所以,浮点数运算是一件非常危险的事情,还请慎重。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM