-0.0 与 IEEE 754浮点标准
2014-06-29 17:35
141 查看
前言
本文针对的是IEEE 754标准,同时测试使用的是遵循IEEE 754标准的Java语言。问题
也许你在Java中使用浮点数时也碰到了这样的情况:+0.0 + -0.0 = +0.0 +0.0 - -0.0 = +0.0 -0.0 + -0.0 = -0.0 -0.0 - -0.0 = +0.0 -1.5 * +0.0 = -0.0 +1.5 * -0.0 = -0.0
“-0.0”是哪里来的?实际上不只是”-0.0”,Java(IEEE 754)还定义了诸如NaN(Not a Number)、正无穷、负无穷的特殊值。这些值是随着浮点数的表示标准而产生的,但也遵循了一定的数学意义。
本文将初步探讨浮点数的表示、舍入,以及浮点数运算的数学属性。
IEEE 754 浮点数表示
IEEE 754标准是20世纪实际80年代推出的,实际上浮点数运算通常不会太多地关注运算的精确性,而把实现速度和简便性看得更重要。十进制与二进制
我们都知道计算机的浮点数不能精确表示某些小数,但这究竟是为什么?这当然不是所谓的“二进制表示法的缺陷”。回想一下,1/3在十进制中如何表示?0.3333….?
任何进制都有小数表示的限制,如十进制所能描述的数值d定义如下:
d=∑i=−nm10i∗di
仅考虑有限长度的编码,十进制表示法不能准确表达如1/3,1/7这样的数。同样,小数的二进制表示法也只能表示那些能够被写成
d=x∗2y
的数。由于我们习惯于日常使用的十进制表示法,于是对程序中的浮点数也经常会带有很多错误的偏见。为什么我在这2货程序里无法精确表示0.1这样简单的小数?你应该认识到你面对的就是”2”进制系统。
浮点数表示
位表示
IEEE浮点标准用 V=(−1)S∗M∗2E的形式来表示一个数:
S(符号):决定数的正负,但对于数值为0的浮点数,符号位解释为特殊情况处理。
M(尾数):是一个二进制小数,它的范围是 1 ~ 2 - ϵ或
0 ~ 1 - ϵ
。其中的ϵ表示一个极小的数,如2
- ϵ表示刚好小于2的数。
E(阶码):对浮点数加权,权重为2的E次幂(可能是负数)。
故将浮点数的位划分成三个字段,以分别对这些值进行编码。
如在单精度浮点数(32位)中,符号位、尾数、阶码分别为1位、8位和23位。
值
根据阶码与尾数的值,浮点数被分为三种不同的情况解释。以32位浮点数为例:规格化的浮点数
阶码 E≠0& E≠255。此时阶码字段被解释为以偏置(biased)形式表示的有符号整数。阶码的值是E=e−Bias,其中e是无符号整数,其位表示就是阶码,而Bias对32位是127,64位是1023。由此产生的指数的取值范围,单精度是-126
~ +127,而双精度是-1022 ~ +1023。
小数字段解释为0.xxx,即小数点在最高有效位的左边。而尾数被定义为M=1+fraction。这也被称作
“implied leading 1” 表示,故尾数范围为 1≤M<2。通过这种表示方法可以获得一个额外的精度位。
非规格化的浮点数
阶码全为0时,所表示的数为非规格化形式。此时阶码值 E=1−Bias,而尾数M=fraction,不包含隐含的1。非规格化的数有两个用途,首先,它们提供了一种表示数值0的方法,因为规格化数中总是有 M≥1,不能表示0。
此时也引出了文章开头提到的问题,即+0.0与-0.0,根据IEEE浮点格式,认为+0.0与-0.0在某些方面(如符号、位表示)是不同的,而在其他方面是相同的(如+0.0 == -0.0)。
非规格化数的另一个功能是表示那些非常接近于0.0的数。
特殊值
阶码全为1,且尾数全为0时,表示的无穷大的值。把两个非常大的数相乘,或者除以零时,无穷大就能够表示溢出的结果。阶码全为1,且尾数 M≠0时,表示”NaN(Not
a Number)”。当一些预算的结果不能是实数或者是无穷大,就会返回NaN。如计算−1−−−√或两个无穷大相减等。
舍入
表示方法限制了浮点数的范围和精度,故浮点数运算只能近似地表示实数运算。因此对于值 x,我们用一种系统的方法,找到“最接近”的能够用期望的浮点形式表示的数 x1,这就是舍入(rounding)。关键的问题是在两个可能值的中间确定舍入方向。
IEEE浮点格式定义了四中不同的舍入方式:
向偶数舍入。也称为向最接近值的舍入,是默认的舍入方式。它采取的方法是:将数字向上或者向下舍入,使得结果的最低有效数字是偶数;
向零舍入。把正数向下取整,负数向上取整,得到 x′,使得|x′|≤x;
向下舍入。把正数和负数都向下舍入,得到 x−,使得x−≤x;
向上舍入。把正数和负数都向上舍入,得到 x+,使得x≤x+。
浮点数运算
由于浮点数表示的局限性,运算的结果实际上是舍入之后的结果 Round(x op y),而不是我们所理解的数学意义上的x op y 的结果。这就是浮点数运算的实质。结果就是,我们必须考虑舍入对浮点数运算的影响。实际上,由于过程中的舍入,浮点运算不具有结合性与分配性,这是浮点运算缺少的最重要的属性,也是对程序员影响最大的属性,即对于某些特殊值,操作数的计算顺序会影响到最终结果。
特殊值的运算规则
当参数中有一个是特殊值,如-0.0,无穷大或NaN时,IEEE标准定义了一些使运算结果更合理的规则,所以就有了前文中特殊值的运算结果。更多的规则有:−0∣∣x∣∣=−0
(−0)⋅(−0)=+0
x+(±0)=x
(−0)+(−0)=(−0)−(+0)=−0
(+0)+(+0)=(+0)−(−0)=+0
x−x=x+(−x)=+0
−0−−−√=−0
−0−∞=+0
∣∣x∣∣−0=−∞
±0×±∞=NaN
±0±0=NaN
参考资料
《深入理解计算机系统》Wiki - Signed Zero
相关文章推荐
- 谈谈浮点数的IEEE标准——未完成
- 四极管:单双精度浮点数的IEEE标准格式
- IEEE 802.11常见标准及2.4GHz、5GHz Wi-Fi介绍
- 解读IEEE标准754:浮点数表示
- IEEE 802标准 IEEE 802 Standards
- IEEE(电子电气工程师协会)802局域网标准
- 以太网和IEEE标准杂记
- 【转】单双精度浮点数的IEEE标准格式
- IEEE 754标准
- 单双精度浮点数的IEEE标准格式
- IEEE 802 标准概述
- 利用共用体和位段获得IEEE标准编码的浮点型数据各部分数值
- IEEE 802.11i:WLAN 安全标准--网络大典
- IEEE 802.11b标准简析
- IEEE 802.11b标准简析
- 谈谈浮点数的IEEE标准——未完成
- IEEE所有标准主页、IETF 6TiSCH主页、中科院信工所和物联网标准等
- IEEE 802标准
- 计算机中浮点数的存储方式 —— IEEE 754-1985 标准
- IEEE Floating Point Standard (IEEE754浮点数表示法标准)