IEEE浮点数提高班

原创 2009年08月19日 00:35:00

(此处为人肉维护的镜像,原文请见: http://csbabel.wordpress.com/ 翻墙请用 Google Reader 查看: http://csbabel.wordpress.com/feed/


谁是本文的读者

本文名为提高班,所以它当然是写给初学者的。高手以及自认为高手的请勿视。如果不确定自己是否需要观看,这里提供一个小测试:但凡不会回答下面的题目的,建议你阅读本文及末尾提供的延伸阅读材料。

先来看这一段程序,如果x是C++内建的数值类型,在什么时候DayOfReckoning()函数会被调用呢?

if ( x != x )
{
    // WTF ???!!!
DayOfReckoning(x);
}

这个题是考计算机数值表示的。答案是:当x为浮点数的NaN的时候。

NaN,它不是一个数

NaN是Not a Number的缩写,就是说它不是一个数。NaN是定义在IEEE 754标准中的特殊值,类似的特殊值还有INF(无穷大,INFinite)。IEEE 754是定义浮点数的标准,有1985和2008两个版本。其中,2008版本还定义了十进制浮点数的标准。

NaN的产生(可以)是这样的(此段文字摘译自WIKI):
1)NaN参与数学运算的结果仍是NaN
2)0/0,正无穷大/正无穷大,正无穷大/负无穷大,负无穷大/正无穷大,负无穷大/负无穷大
3)0和正/负无穷大相乘
4)正无穷大+负无穷大,负无穷大加正无穷大
5)数学上无解的一些函数值,比如:负数的平方根,对2.0的求反正弦,等等

第一条说明了NaN在运算中的“传染性”。如果不慎在某处引入了NaN,那么之后的算式值很可能就一直是NaN了。所以在涉及浮点数值运算时一定要注意NaN的存在。

回过头来解释前面的题目:NaN永远不等于自己,所以说NaN == NaN永远为false,而NaN != NaN永远为true。这是一个相当特殊的情况:即使参与比较的两个NaN的内存表示是一模一样的,但它们仍然是不等的。

更深一步地说,NaN有两种,一种是Quiet NaN,另一种是Signalling NaN。在使用时,Signalling NaN会立即引发异常,然后将自身变为Quiet NaN;Quiet NaN的行为比较安静,在算术运算中它不会引发异常,只是将运算结果“传染”为NaN(但是在某些不接受NaN的地方仍会引发异常)。

INF,它溢出到无穷大

INF就是无穷大,在浮点数中,有+INF和-INF两种。INF在数学上有对应的概念,所以它比NaN更好理解一些。比如用1/0,得到的结果就是INF

0,它竟然还有正负

在IEEE浮点数中,0也是特殊的,因为它有+0和-0两种(“正零”和“负零”)。其中,1除以“负0”等于“负无穷大”,1除以“正0”等于“正无穷大”。

舍入,它可不是“四舍五入”

舍入算法对我们多数人来说意味着“四舍五入”。这个在上学时就学过了,但它却会给舍入之后的数带来扩大的趋势。在买卖方之间,民俗传统中一直有“五 刨六撩”一说,“五刨”是说将5及5以下的舍去,“六撩”是说将6及6以上的进位,这种舍入算法有整体减小的趋势,体现了小生意人让利的“诚意”。那么, 更好的舍入算法是什么样的呢?

IEEE754中定义了最基本的舍入算法:Rounds to nearest, ties to even(even在这里是“偶数”的意思)。这种算法将4及4以下的数抛弃,6及6以上的数进位,如果要舍入的最高位是5的话,则将要保留的最低位圆整 到最接近的偶数(这里说的“偶数”包括0)。比如:

89.64 --> 90
98.46 --> 98
1919.54 --> 1920
1918.55 --> 1918

对于大量均匀分布的数来说,这种50%概率算法保证了舍入后的数没有放大或者缩小的趋势。在银行里都是用的这种算法,做过金融类程序的对此应该印象深刻的。

除了上面提到的“Ties To Even算法”之外,还有几种舍入算法,因为定义得非常清晰和明确,这里不再多说,详情请见参考资料。

总结

即便是使用高级语言,只要使用浮点数,就有可能碰到上面提到的问题。可惜国内的教材多数只讲了浮点数最基本的存储形式,对于上面几个很重要的话题竟 然只字未提。本文存在的意义也在于此。据说,每在文章中加入一个二进制表示公式,文章的读者就会减少一半,所以我没有放任何的公式。感兴趣的可以用鼠标猛 烈敲击参考资料/延伸阅读。

参考资料/延伸阅读

1、http://en.wikipedia.org/wiki/IEEE_754-2008
2、http://en.wikipedia.org/wiki/IEEE_754-1985
3、http://en.wikipedia.org/wiki/Signed_zero
4、http://en.wikipedia.org/wiki/Not_a_Number
5、IEEE标准

致谢

感谢Jun Yang指出文中的问题(http://blog.csdn.net/lovetheme)

解读IEEE标准754-浮点数机制

  • 2011年01月24日 14:38
  • 121KB
  • 下载

谈谈浮点数的IEEE标准——未完成

IEEE754标准是现在最通用的二进制算术运算标准,它被用于Sun,DEC,HP,IBM工作站以及所有的个人计算机。IEEE算术运算包括两类浮点数:单精度(float型,32位字长)和双精度(doub...
  • Augusdi
  • Augusdi
  • 2013年04月15日 15:15
  • 855

ieee754--浮点数标准

  • 2009年07月13日 11:59
  • 97KB
  • 下载

IEEE754,浮点数的精度

http://zh.wikipedia.org/wiki/IEEE_754 IEEE二进制浮点数算术标准(IEEE 754)是1980年代以来最广泛使用的浮点数运算标准,为许多CPU与浮...

IEEE 754浮点数

  • 2014年03月04日 17:55
  • 462KB
  • 下载

IEEE754浮点数据

  • 2012年09月23日 20:38
  • 2.17MB
  • 下载

关于一道IEEE754浮点数标准的百度面试题再论

一个非常简单的C语言例子,可以用来很好的学习IEEE754浮点数标准,但最后又引出一个问题~~~...
  • fovwin
  • fovwin
  • 2013年08月06日 19:15
  • 1993

IEEE754浮点数标准

  • 2015年10月09日 23:37
  • 93KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IEEE浮点数提高班
举报原因:
原因补充:

(最多只允许输入30个字)