标签:小数点
在计算机系统的发展过程中,曾经提出过多种方法表达实数。比如定点数表示法, 这种表示方法将小数点的位置固定在某一个位置,比如: 11001000.00110001,这个16位(2字节) 的定点数用前面8位表示整数部分,后面8位表示小数部分,这种方法直观,但是固定的小数点位置决定了固定位数的整数部分和小数部分,不利于同时表达特别大的数或者特别小的数。最终,绝大多数现代计算机遵循IEEE754,即IEEE二进制浮点数算数标准,利用科学计数法来表达实数,即用一个尾数(Mantissa or significand),一个基数(Base),一个指数(Exponent)以及一个表示正负的符号来表达实数。比如 123.45 用十进制科学计数法可以表达为 1.2345 × 10^2 ,其中1.2345 为尾数,10 为基数,2为指数。浮点数利用指数达到了浮动小数点的效果,从而可以灵活地表达更大范围的实数。
IEEE 754标准定义了五种浮点数格式,使用基数和该格式占用的内存比特数命名,五种格式分别为:
各种编程语言和编译器一般都支持前两种格式,分别对应于float和double,对于后一种二进制高双精度128位浮点数,一般编译器使用80位表示,也有极个别的编译器将他们视为128位。
在IEEE标准中,浮点数在内存中的表示是将特定长度的连续字节的所有二进制位按特定长度划分为符号域,指数域和尾数域三个连续域。 例如,对于float类型的数据,其在内存中的表示为:
对于double类型,其表示形式如下:
从上面可以看出,float类型在内存中占用的位数为:
我们已经明白了浮点数在内存中的储存形式。那么下面就用一个例子来强化一下我们对浮点数的理解。 假设我们内存中有一个32位的浮点数:
解释:
s: 1-表示负数
e: 10000010->130->(130-127)=3,也即尾数部分小数点向右移3位。
m: 10110000000000000000000,尾数加上前面省略的1和小数点为:1.10110000000000000000000.
现在三个部分都已经算出来了,通过指数值调整小数点的位置,得到结果为:
1101.10000000000000000000
转换成10进制,整数部分为:
最后整数部分加上小数部分,再加上符号,所表示的实数就是:
我们已经知道,指数域实际可以表达的指数值的范围为-127 到128 之间(包含两端)。其中,值-127(保存为 全 0)以及+128(保存为全1)保留用作特殊值的处理。
浮点数中的特殊值主要用于特殊情况或者错误的处理。比如在程序对一个负数进行开平方时,一个特殊的返回值将用于标记这种错误,该值为NaN(Nota Number)。没有这样的特殊值,对于此类错误只能粗暴地终止计算。除了NaN 之外,IEEE标准还定义了±0,±∞ 以及非规范化数(DenormalizedNumber)。
对于单精度浮点数,所有这些特殊值都由保留的特殊指数值-127 和128 来编码。NaN的指数为128(指数域全为1),且尾数域不等于零。IEEE 标准没有要求具体的尾数域,所以NaN 实际上不是一个,而是一族。不同的实现可以自由选择尾数域的值来表达NaN,比如Java 中的常量Float.NaN 的浮点数可能表达为01111111110000000000000000000000,其中尾数域的第一位为 1,其余均为 0(不计隐藏的一位),但这取决系统的硬件架构。Java 中甚至允许程序员自己构造具有特定位模式的 NaN 值(通过Float.intBitsToFloat() 方法)。比如,程序员可以利用这种定制的 NaN 值中的特定位模式来表达某些诊断信息。
和NaN一样,特殊值无穷的指数部分同样为128,不过无穷的尾数域必须全部为0。无穷用于表达计算中产生的上溢(Overflow)问题。比如两个极大的数相乘时,尽管两个操作数本身可以用保存为浮点数,但其结果可能大到无法保存为浮 点数,而必须进行舍入。根据 IEEE 标准,此时不是将结果舍入为可以保存的最大的浮点数(因为这个数可能离实际的结果相差太远而毫无意义),而是将其舍入为无穷。对于负数结果也是如此,只不 过此时舍入为负无穷,也就是说符号域为 1 的无穷。
因为IEEE 标准的浮点数格式中,小数点左侧的1 是隐藏的,而零显然需要尾数必须是零。所以,零也就无法直接用这种格式表达而只能特殊处理。
实际上,零保存为尾数域为全为0,指数域为emin - 1 = -127,也就是说指数域也全为 0。考虑到符号域的作用,所以存在着两个零,即 +0 和 -0。不同于正负无穷之间是有序的,IEEE 标准规定正负零是相等的。
零有正负之分,的确非常容易让人困惑。这一点是基于数值分析的多种考虑,经利弊权衡后形成的结果。有符号的零可以避免运算中,特别是涉及无穷的运算 中,符号信息的丢失。举例而言,如果零无符号,则等式 1/(1/x) = x 当x = ±∞ 时不再成立。原因是如果零无符号,1 和正负无穷的比值为同一个零,然后1 与 0 的比值为正无穷,符号没有了。解决这个问题,除非无穷也没有符号。但是无穷的符号表达了上溢发生在数轴的哪一侧,这个信息显然是不能不要的。零有符号也造 成了其它问题,比如当 x=y 时,等式1/x = 1/y 在 x 和 y 分别为 +0 和 -0 时,两端分别为正无穷和负无穷而不再成立。当然,解决这个问题的另一个思路是和无穷一样,规定零也是有序的。但是,如果零是有序的,则即使 if(x==0) 这样简单的判断也由于可能是 ±0而变得不确定了。两害取其轻者,零还是无序的好。
标签:小数点
原文地址:http://blog.csdn.net/techx/article/details/43830781