




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
转载浮点数1.什么是浮点数在计算机系统的发展过程中,曾经提出过多种方法表达实数。典型的比如相对于浮点数的定点数(Fixed Point Number)。在这种表达方式中,小数点固定的位于实数所有数字中间的某个位置。货币的表达就可以使用这种方式,比如99.00或者00.99可以用于表达具有四位精度(Precision),小数点后有两位的货币值。由于小数点位置固定,所以可以直接用四位数值来表达相应的数值。SQL中的NUMBER数据类型就是利用定点数来定义的。还有一种提议的表达方式为有理数表达方式,即用两个整数的比值来表达实数。定点数表达法的缺点在于其形式过于僵硬,固定的小数点位置决定了固定位数的整数部分和小数部分,不利于同时表达特别大的数或者特别小的数。最终,绝大多数现代的计算机系统采纳了所谓的浮点数表达方式。这种表达方式利用科学计数法来表达实数,即用一个尾数(Mantissa,尾数有时也称为有效数字Significand;尾数实际上是有效数字的非正式说法),一个基数(Base),一个指数(Exponent)以及一个表示正负的符号来表达实数。比如123.45用十进制科学计数法可以表达为1.2345 102,其中1.2345为尾数,10为基数,2为指数。浮点数利用指数达到了浮动小数点的效果,从而可以灵活地表达更大范围的实数。2.IEEE浮点数计算机中是用有限的连续字节保存浮点数的。在IEEE标准中,浮点数是将特定长度的连续字节的所有二进制位分割为特定宽度的符号域,指数域和尾数域三个域,其中保存的值分别用于表示给定二进制浮点数中的符号,指数和尾数。这样,通过尾数和可以调节的指数(所以称为浮点)就可以表达给定的数值了。IEEE 754指定:n两种基本的浮点格式:单精度和双精度。IEEE单精度格式具有24位有效数字精度,并总共占用32位。IEEE双精度格式具有53位有效数字精度,并总共占用64位。n两种扩展浮点格式:单精度扩展和双精度扩展。此标准并未规定这些格式的精确精度和和大小,但它指定了最小精度和大小。例如,IEEE双精度扩展格式必须至少具有64位有效数字精度,并总共占用至少79位。具体的格式参见下面的图例:3.浮点格式浮点格式是一种数据结构,用于指定包含浮点数的字段、这些字段的布局及其算术解释。浮点存储格式指定如何将浮点格式存储在内存中。IEEE标准定义了这些格式,但具体选择哪种存储格式由实现工具决定。汇编语言软件有时取决于所使用的存储格式,但更高级别的语言通常仅处理浮点数据类型的语言概念。这些类型在不同的高级语言中具有不同的名称,并且与表中所示的IEEE格式相对应。IEEE精度C、C+Fortran(仅限SPARC)单精度floatREAL或REAL*4双精度doubleDOUBLE PRECISION或REAL*8双精度扩展long doubleREAL*16IEEE 754明确规定了单精度浮点格式和双精度浮点格式,并为这两种基本格式分别定义了一组扩展格式。表中显示的long double和REAL*16类型适用于IEEE标准定义的一种双精度扩展格式。3.1.单精度格式IEEE单精度格式由三个字段组成:23位小数f;8位偏置指数e;以及1位符号s。这些字段连续存储在一个32位字中(如下图所示)。0:22位包含23位小数f,其中第0位是小数的最低有效位,第22位是最高有效位。IEEE标准要求浮点数必须是规范的。这意味着尾数的小数点左侧必须为1,因此我们在保存尾数的时候,可以省略小数点前面这个1,从而腾出一个二进制位来保存更多的尾数。这样我们实际上用23位长的尾数域表达了24位的尾数。23:30位包含8位偏置指数e,第23位是偏置指数的最低有效位,第30位是最高有效位。8位的指数为可以表达0到255之间的256个指数值。但是,指数可以为正数,也可以为负数。为了处理负指数的情况,实际的指数值按要求需要加上一个偏差(Bias)值作为保存在指数域中的值,单精度数的偏差值为127;偏差的引入使得对于单精度数,实际可以表达的指数值的范围就变成-127到128之间(包含两端)。在本文中,最小指数和最大指数分别用emin和emax来表达。稍后将介绍实际的指数值-127(保存为全0)以及+128(保存为全1)保留用作特殊值的处理。最高的第31位包含符号位s。s为0表示数值为正数,而s为1则表示负数。3.2.双精度格式IEEE双精度格式由三个字段组成:52位小数f;11位偏置指数e;以及1位符号s。这些字段连续存储在两个32位字中(如下图所示)。在SPARC体系结构中,较高地址的32位字包含小数的32位最低有效位,而在x86体系结构中,则较低地址的32-位字包含小数的32位最低有效位。如果用f31:0表示小数的32位最低有效位,则在这32位最低有效位中,第0位是整个小数的最低有效位,而第31位则是最高有效位。在另一个32位字中,0:19位包含20位小数的最高有效位f51:32,其中第0位是这20位最高有效位中的最低有效位,而第19位是整个小数的最高有效位;20:30位包含11位偏置指数e,其中第20位是偏置指数的最低有效位,而第30位是最高有效位;最高的第31位包含符号位s。上图将这两个连续的32位字按一个64位字那样进行了编号,其中0:51位包含52位小数f,其中第0位是小数的最低有效位,第51位是最高有效位。IEEE标准要求浮点数必须是规范的。这意味着尾数的小数点左侧必须为1,因此我们在保存尾数的时候,可以省略小数点前面这个1,从而腾出一个二进制位来保存更多的尾数。这样我们实际上用52位长的尾数域表达了53位的尾数。52:62位包含11位偏置指数e,第52位是偏置指数的最低有效位,第62位是最高有效位。11位的指数为可以表达0到2047之间的2048个指数值。但是,指数可以为正数,也可以为负数。为了处理负指数的情况,实际的指数值按要求需要加上一个偏差(Bias)值作为保存在指数域中的值,单精度数的偏差值为1023;偏差的引入使得对于单精度数,实际可以表达的指数值的范围就变成-1023到1024之间(包含两端)。在本文中,最小指数和最大指数分别用emin和emax来表达。稍后将介绍实际的指数值-1023(保存为全0)以及+1024(保存为全1)保留用作特殊值的处理。最高的第63位包含符号位s。s为0表示数值为正数,而s为1则表示负数。3.3.双精度扩展格式(SPARC)SPARC浮点环境的四倍精度格式符合双精度扩展格式的IEEE定义。四倍精度格式占用32位字并包含以下三个字段:112位小数f、15位偏置指数e和1位符号s。这三个字段连续存储,如图2-3所示。地址最高的32位字包含小数的32位最低有效位,用f31:0表示。紧邻的两个32位字分别包含f63:32和f95:64。下面的0:15位包含小数的16位最高有效位f111:96,其中第0位是这16位的最低有效位,而第15位是整个小数的最高有效位。16:30位包含15位偏置指数e,其中第16位是该偏置指数的最低有效位,而第30位是最高有效位;第31位包含符号位s。下图将这四个连续的32位字按一个128位字那样进行了编号,其中0:111位存储小数f;112:126位存储15位偏置指数e;而第127位存储符号位s。3.4.双精度扩展格式(x86)该浮点环境双精度扩展格式符合双精度扩展格式的IEEE定义。它包含四个字段:63位小数f、1位显式前导有效数位j、15位偏置指数e以及1位符号s。在x86体系结构系列中,这些字段连续存储在十个相连地址的8位字节中。由于UNIXSystem V Application Binary Interface Intel 386 Processor Supplement (Intel ABI)要求双精度扩展参数,从而占用堆栈中三个相连地址的32位字,其中地址最高字的16位最高有效位未用,如下图所示。地址最低的32位字包含小数的32位最低有效位f31:0,其中第0位是整个小数的最低有效位,而第31位则是32位最低有效位的最高有效位。地址居中的32位字中,0:30位包含小数的31位最高有效位f62:32(其中第0位是这31位最高有效位的最低有效位,而第30位是整个小数的最高有效位);地址居中32位字的第31位包含显式前导有效数位j。地址最高的32位字中,0:14位包含15位偏置指数e,其中第0位是该偏置指数的最低有效位,而第14位是最高有效位;第15位包含符号位s。虽然地址最高的32位字的最高16位未被x86体系结构系列使用,但如上所述,它们对于符合Intel ABI规定是至关重要的。4.将实数转换成浮点数4.1浮点数的规范化同样的数值可以有多种浮点数表达方式,比如上面例子中的123.45可以表达为12.345 101,0.12345 103或者1.2345 102。因为这种多样性,有必要对其加以规范化以达到统一表达的目标。规范的(Normalized)浮点数表达方式具有如下形式:d.dd.d e, (0 di )其中d.dd.d即尾数,为基数,e为指数。尾数中数字的个数称为精度,在本文中用p来表示。每个数字d介于0和基数之间,包括0。小数点左侧的数字不为0。基于规范表达的浮点数对应的具体值可由下面的表达式计算而得:(d0+d1-1+ . +dp-1-(p-1)e, (0 di )对于十进制的浮点数,即基数等于10的浮点数而言,上面的表达式非常容易理解,也很直白。计算机内部的数值表达是基于二进制的。从上面的表达式,我们可以知道,二进制数同样可以有小数点,也同样具有类似于十进制的表达方式。只是此时等于2,而每个数字d只能在0和1之间取值。比如二进制数1001.101相当于1 23+ 0 22+ 0 21+ 1 20+ 1 2-1+ 0 2-2+ 1 2-3,对应于十进制的9.625。其规范浮点数表达为1.001101 23。4.2根据精度表示浮点数以上面的9.625为例,其规范浮点数表达为1.001101 23,因此按单精度格式表示为:1 10000010 00110100000000000000000同理按双精度格式表示为:1 10000000010 00110100000000000000000000000000000000000000000000005.特殊值通过前面的介绍,你应该已经了解的浮点数的基本知识,这些知识对于一个不接触浮点数应用的人应该足够了。不过,如果你兴趣正浓,或者面对着一个棘手的浮点数应用,可以通过本节了解到关于浮点数的一些值得注意的特殊之处。我们已经知道,单精度浮点数指数域实际可以表达的指数值的范围为-127到128之间(包含两端)。其中,值-127(保存为全0)以及+128(保存为全1)保留用作特殊值的处理。本节将详细IEEE标准中所定义的这些特殊值。浮点数中的特殊值主要用于特殊情况或者错误的处理。比如在程序对一个负数进行开平方时,一个特殊的返回值将用于标记这种错误,该值为NaN(Not a Number)。没有这样的特殊值,对于此类错误只能粗暴地终止计算。除了NaN之外,IEEE标准还定义了0,以及非规范化数(Denormalized Number)。对于单精度浮点数,所有这些特殊值都由保留的特殊指数值-127和128来编码。如果我们分别用emin和emax来表达其它常规指数值范围的边界,即-126和127,则保留的特殊指数值可以分别表达为emin- 1和emax+ 1;。基于这个表达方式,IEEE标准的特殊值如下所示:其中f表示尾数中的小数点右侧的(Fraction)部分。第一行即我们之前介绍的普通的规范化浮点数。随后我们将分别对余下的特殊值加以介绍。5.1NaNNaN用于处理计算中出现的错误情况,比如0.0除以0.0或者求负数的平方根。由上面的表中可以看出,对于单精度浮点数,NaN表示为指数为emax+ 1 = 128(指数域全为1),且尾数域不等于零的浮点数。IEEE标准没有要求具体的尾数域,所以NaN实际上不是一个,而是一族。不同的实现可以自由选择尾数域的值来表达NaN,比如Java中的常量Float.NaN的浮点数可能表达为01111111110000000000000000000000,其中尾数域的第一位为1,其余均为0(不计隐藏的一位),但这取决系统的硬件架构。Java中甚至允许程序员自己构造具有特定位模式的NaN值(通过FBitsToFloat()方法)。比如,程序员可以利用这种定制的NaN值中的特定位模式来表达某些诊断信息。定制的NaN值,可以通过Float.isNaN()方法判定其为NaN,但是它和Float.NaN常量却不相等。实际上,所有的NaN值都是无序的。数值比较操作符,和=在任一操作数为NaN时均返回false。等于操作符=在任一操作数为NaN时均返回false,即使是两个具有相同位模式的NaN也一样。而操作符!=则当任一操作数为NaN时返回true。这个规则的一个有趣的结果是x!=x当x为NaN时竟然为真。可以产生NaN的操作如下所示:此外,任何有NaN作为操作数的操作也将产生NaN。用特殊的NaN来表达上述运算错误的意义在于避免了因这些错误而导致运算的不必要的终止。比如,如果一个被循环调用的浮点运算方法,可能由于输入的参数问题而导致发生这些错误,NaN使得 即使某次循环发生了这样的错误,也可以简单地继续执行循环以进行那些没有错误的运算。你可能想到,既然Java有异常处理机制,也许可以通过捕获并忽略异常达到相同的效果。但是,要知道,IEEE标准不是仅仅为Java而制定的,各种语言处理异常的机制不尽相同,这将使得代码的迁移变得更加困难。何况,不是所有语言都有类似的异常或者信号(Signal)处理机制。注意:Java中,不同于浮点数的处理,整数的0除以0将抛出java.lang.ArithmeticException异常。5.2无穷和NaN一样,特殊值无穷(Infinity)的指数部分同样为emax+ 1 = 128,不过无穷的尾数域必须为零。无穷用于表达计算中产生的上溢(Overflow)问题。比如两个极大的数相乘时,尽管两个操作数本身可以用保存为浮点数,但其结果可能大到无法保存为浮点数,而必须进行舍入。根据IEEE标准,此时不是将结果舍入为可以保存的最大的浮点数(因为这个数可能离实际的结果相差太远而毫无意义),而是将其舍入为无穷。对于负数结果也是如此,只不过此时舍入为负无穷,也就是说符号域为1的无穷。有了NaN的经验我们不难理解,特殊值无穷使得计算中发生的上溢错误不必以终止运算为结果。无穷和除NaN以外的其它浮点数一样是有序的,从小到大依次为负无穷,负的有穷非零值,正负零(随后介绍),正的有穷非零值以及正无穷。除NaN以外的任何非零值除以零,结果都将是无穷,而符号则由作为除数的零的符号决定。回顾我们对NaN的介绍,当零除以零时得到的结果不是无穷而是NaN。原因不难理解,当除数和被除数都逼近于零时,其商可能为任何值,所以IEEE标准决定此时用NaN作为商比较合适。5.3有符号的零因为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)这样简单的判断也由于x可能是0而变得不确定了。两害取其轻者,零还是无序的好。5.4非规范化数我们来考察浮点数的一个特殊情况。选择两个绝对值极小的浮点数,以单精度的二进制浮点数为例,比如1.001 2-125和1.0001 2-125这两个数(分别对应于十进制的2.6448623 10-38和2.4979255 10-38)。显然,他们都是普通的浮点数(指数为-125,大于允许的最小值-126;尾数更没问题),按照IEEE 754可以分别保存为00000001000100000000000000000000(0x1100000)和00000001000010000000000000000000(0x1080000)。现在我们看看这两个浮点数的差值。不难得出,该差值为0.0001 2-125,表达为规范浮点数则为1.0 2-129。问题在于其指数大于允许的最小指数值,所以无法保存为规范浮点数。最终,只能近似为零(Flush to Zero)。这中特殊情况意味着下面本来十分可靠的代码也可能出现问题:if (x != y) z = 1 / (x -y);正如我们精心选择的两个浮点数展现的问题一样,即使x不等于y,x和y的差值仍然可能绝对值过小,而近似为零,导致除以0的情况发生。为了解决此类问题,IEEE标准中引入了非规范(Denormalized)浮点数。规定当浮点数的指数为允许的最小指数值,即emin时,尾数不必是规范化的。比如上面例子中的差值可以表达为非规范的浮点数0.001 2-126,其中指数-126等于emin。注意,这里规定的是不必,这也就意味着可以。当浮点数实际的指数为emin,且指数域也为emin时,该浮点数仍是规范的,也就是说,保存时隐含着一个隐藏的尾数位。为了保存非规范浮点数,IEEE标准采用了类似处理特殊值零时所采用的办法,即用特殊的指数域值emin- 1加以标记,当然,此时的尾数域不能为零。这样,例子中的差值可以保存为00000000000100000000000000000000(0x100000),没有隐含的尾数位。有了非规范浮点数,去掉了隐含的尾数位的制约,可以保存绝对值更小的浮点数。而且,也由于不再受到隐含尾数域的制约,上述关于极小差值的问题也不存在了,因为所有可以保存的浮点数之间的差值同样可以保存。6.范围和精度很多小数根本无法在二进制计算机中精确表示(比如最简单的0.1)由于浮点数尾数域的位数是有限的,为此,浮点数的处理办法是持续该过程直到由此得到的尾数足以填满尾数域,之后对多余的位进行舍入。换句话说,除了我们之前讲到的精度问题之外,十进制到二进制的变换也并不能保证总是精确的,而只能是近似值。事实上,只有很少一部分十进制小数具有精确的二进制浮点数表达。再加上浮点数运算过程中的误差累积,结果是很多我们看来非常简单的十进制运算在计算机上却往往出人意料。这就是最常见的浮点运算的不准确问题。参见下面的Java示例:System.out.print(34.6-34.0= + (34.6f-34.0f);这段代码的输出结果如下:34.6-34.0=0.5999985产生这个误差的原因是34.6无法精确的表达为相应的浮点数,而只能保存为经过舍入的近似值。这个近似值与34.0之间的运算自然无法产生精确的结果。存储格式的范围和精度格式有效数字(二进制)最小正正规数最大正数有效数字(十进制)单精241.175. 10-383.402. 10+386-9双精度532.225. 10-3081.797.10+30815-17双精度扩展(SPARC)1133.362
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 更新钢管井施工方案(3篇)
- 道路石材面板施工方案(3篇)
- 严管厚爱系列活动方案策划(3篇)
- 景区许愿活动策划方案模板(3篇)
- 长宁企业年会活动策划方案(3篇)
- 机械模具考试题库及答案
- 教学课件里能用党旗党徽
- 小学学科融合题目及答案
- 改写寻隐者不遇作文14篇
- 文化娱乐行业节目分类表
- 台湾-国民年金保险课件
- 血透室运用PDCA循环降低无肝素透析凝血发生率品管圈成果汇报
- 三叉神经痛微球囊压迫术的护理
- 主持人妆 男主持人上镜妆
- 安全伴我行-大学生安全教育智慧树知到答案章节测试2023年哈尔滨工程大学
- LY/T 1828-2009黄连木栽培技术规程
- 安全文明施工措施费清单五篇
- X射线衍射课件(XRD)
- 常见皮肤病的种类及症状图片、简介大全课件
- 高中化学学法指导课件
- 吊篮拆除安全技术交底方案
评论
0/150
提交评论