zoukankan      html  css  js  c++  java
  • 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也是浮点数类型,只是精度更高,仍然有精度损失存在,所以,浮点数运算是一件非常危险的事情,还请慎重。

  • 相关阅读:
    Session机制详解
    JDK各个版本比较 JDK5~JDK9
    CAS 自旋锁
    OAuth2.0认证和授权原理
    微信二维码登录原理
    Django Restframework 实践(一)
    ESXI 5.5卡在LSI_MR3.V00
    理解RESTful架构
    RESTful API 设计指南
    python 异步 select pooll epoll
  • 原文地址:https://www.cnblogs.com/krockey/p/5803152.html
Copyright © 2011-2022 走看看