`
Dustin
  • 浏览: 310417 次
  • 性别: Icon_minigender_1
  • 来自: 广州/成都
社区版块
存档分类
最新评论

1.03 - 0.42 = ?

阅读更多

最初发表在这里

 

0.61。一定确定以及肯定?看看计算机是怎样回答的:

一号选手C/C++的答案是:printf("%5.20f", 1.03-0.42);  output = 0.61000000000000010000
 二号选手Java的答案是:System.out.printf("%5.20f", 1.03-0.42) ; output = 0.61000000000000010000
三号选手Python的答案是:print "%5.20f"%(1.03-0.42); output = 0.61000000000000010000

     三名选手竟然异口同声说答案是0.61000000000000010000,而不是我们小学生都可以一定确定以及肯定的答案0.61,为何呢?原来,这三种(还有其它更多的)语言都是按照 IEEE-754 标准来规定浮点数的存储格式的。由于师出同门,得到相同的答案也就不足为奇了。令人不解的是它们得到的结果明摆着是错误的,我们为什么还要计算机遵守这个规定呢?呵呵,没办法,由于当前我们使用的计算机都是遵循冯.诺依曼体系结构的,只能处理离散数据,而且在计算机内部数据是以二进制的形式存放的,因此,对于实数这样的连续概念,我们只能通过离散量来模拟。这跟用多边形来模拟圆的道理是一样的,如果多边形的边越多,多边形跟圆的切点就越多,也就意味着该多边形与圆越相似,当边数趋于无穷时,多边形也就跟圆重合了。也就是说,我们只有通过无穷这个概念使得离散量可以精确地模拟出连续量,但是,在计算机科学中,我们是不能表示出无穷这个概念的。正是这个原因,用计算机来表示一个实数,在大多数情况下得到的都只是一个近似的结果。
    http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html对IEEE-754做了一个很好的描述,大家可以参考一下。总的来说,在IEEE-754中,浮点数分为三个部分(以32位浮点数为例):
    1、符号位,决定该浮点数的正负(1位)
    2、指数,决定浮点数的 大小范围(8位)
    3、尾数,决定浮点数的表示精度(23位,由于使用规范化表示,最高位为1,因此可以表示24位的精度)。
    可以看出来,尾数的位数越多,我们所能精确表示的实数就越多(在多边形和圆的例子中就是两者的切点更多了)。因此,double类型的数据所能精确表示的实数个数要远远多于float类型的数据,其代价就是多用一倍的存储空间。但是,虽然这样,对于实数这个无穷无尽的庞然大物来说,double也是无能为力,还是有很多数字double类型都无法精确表示出来,12345.691234566778就是这样的一个例子。
     因此,如果我们要求精确的答案,就要避免使用float和double类型的数据,特别是在货币计算方面,这一点在Effective Java item 31中有详细的描述。此外,这也解释了为什么在判断两个浮点数是否相等时不能直接用相等符号进行比较,而要通过跟一个表示特定精度的数据进行比较得知。

if( 1.03-0.42 == 0.61){   
     System.out.println("Aha!");
  }else{
    System.out.println("Huh?");
  }
output = Huh?

if( (1.03-0.42)- 0.61 < 10e-6){   
     System.out.println("Aha!");
  }else{
    System.out.println("Huh?");
  }
output = Aha!

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics