深入理解计算机系统(CSAPP):第二章.信息的表示和处理

2.4 浮点数

        浮点表示对形如 V = x * 2^{y}的有理数进行编码。他对执行涉及非常大的数字\left | V \right | \gg 0、非常接近于0的数字 \left | V \right | \ll 1,以及更普遍的作为实数运算的近似值的计算,是很有用的。

        直到20世纪80年代,每个计算机制造商都设计了自己的表示浮点数的规则,以及对浮点数执行运算的细节。另外,他们常常不会太多的关注运算的精确性,而把实现的速度和简便性看的比数字的精确性更重要。

        大约在1985年,这些情况随着IEEE标准754的推出而改变了,这是一个仔细制定的表示浮点数及其运算的标准。这项工作从1976年开始有Intel赞助的,与8087的设计同时进行,8087是一种为8086处理器提供浮点支持的芯片,他们请William Kahan作为顾问,帮助设计未来处理器浮点标准。目前,实际上所有的计算机都支持这个后来被称为IEEE浮点的标准。着大大的提高了科学应用程序在不同机器上的可移植性。

        在本节中,我们将看到IEEE浮点格式中数字是如何表示的。我们还将探讨舍入的问题。即当一个数字不能被准确的表示为这种格式时,就必须向上调整或者向下调整。然后我们将探讨加法、乘法和关系运算符的数学属性。

2.4.1 二进制小数

        理解浮点数的第一步是考虑含有小数值的二进制数字。首先,让我们来看看更熟悉的十进制表示法。十进制表示法使用如下形式的表示:

   d_{m}d_{m-1}....d_{1}d_{0}.d_{-1}d_{-2}...d_{-n}

其中每个十进制数的取值范围是0~9。这个表达描述的数值d定义如下:

        d =\sum_{i=-n}^{m} 10^{i} * d_{i}

        数字权的定义与十进制小数点符号相关,这意味着小数点左边的数字的权是10的正幂,得到整数值,而小数点右边的数字的权是10的负幂,得到小数值。

        假定我们仅考虑有限长度的编码,那么十进制表示法不能准确的表达像 1/3和 5/7这样的数,类似,小数的二进制表示法只能表示那些能够被写成 x*2^{y} 的数。其他的值只能近似的表示。例如,数字1/5可以用十进制小数0.20精确表示。不过我们并不能把它们准确的表示为一个二进制小数,我们只能近似的表示他,增加二进制表示的长度可以提高表示的精度。

2.4.2 IEEE浮点表示

        前一节中谈到的定点表示法不能很有效的表示非常大的数字。例如,表达式5*2^{100}是用100后面跟随100个零的位模式来表示的。相反,我们希望通过给定x和y的值,来表示 x *2^{y}的数。

        IEEE浮点标准用v=\left ( -1 \right )^{s} *M * 2^{E}的形式来表示一个数:

  • 符号(sign) s决定这个数是负数(s=1) 还是正数(s=0),而对于数值0的符号位解释作为特殊情况处理。
  • 尾数(significand) M是一个二进制小数。
  • 阶码(exponent) E的作用是对浮点数加权,这个权重是2的E次幂。

        将浮点数的位表示划分为三个字段,分别对这些值进行编码:

  • 一个单独的符号位s 直接编码符号s。
  • k位的阶码字段 exp= e_{k-1}...e_{1}e_{0} 编码阶码E。
  • n位小数字段 frac = f_{n-1}...f_{1}f_{0}编码尾数M,但是编码出来的值也依赖于阶码字段的值是否等于0

        图2-32中给出了将这3个字段装进字中最常见的格式。在单精度浮点格式中,s、exp和frac 字段分别为1位,k=8位和n=23位,得到一个32位的表示。在双精度中,s、exp和frac 字段分别为1位、k=11位和n=52位,得到一个64位表示

2-32 标准浮点格式

        给定位表示,根据exp的值,被编码的值可以分成三种不同的情况。图2-33 说明了对单精度格式的情况 

2-33 单精度浮点数值的分类

 情况1:规格化的值:

        这种情况是最普遍的。当exp 的位模式既不全为0,也不全为1时,都属于这类情况。在这种情况中,阶码字段被解释为偏置形式表示的有符号整数。也就是说,阶码的值是 E = e-Bias,其中e是无符号数,其位表示为 e_{k-1}...e_{1}e_{0}而Bias是一个等于2^{k-1} -1的偏置值。由此产生指数的取值范围。

        小数字段frac被解释为描述小数值f,其中0\leq f < 1,其二进制表示为0.f_{n-1}....f_{1}f_{0},也就是二进制小数在最高有效位的左边。尾数定义为 M = 1+f。有时,这种方式也叫做隐含的以1开头的表示,因为我们可以吧M看成一个二进制表达式为 1.f_{n-1}f_{n-2}....f_{0}。既然我们总是能够调整阶码E,使得尾数M在范围 1\leq M < 2之中,那么这种表示方法是一种轻松获得一个额外精度位的技巧。既然第一位总是等于1,那么我们就不需要显式的表示他。

 情况2:非规格化的值

        当阶码域全0时,所表示的数是非规格化形式。在这种情况下,阶码值是E = 1-Bias,而尾数M=f,也就是小数字段的值,不包含隐含的开头的1。

        非规格化数有两个用途。首先,他们提供了一种表示数值0的方法,因为使用规格数,我们必须总是是M≥1,因此我们不能表示0。实际上,+0.0的浮点表示位模式为全0,符号位是0,阶码字段全为0,而小数域也全是0,这就得到了M=f=0。令人奇怪的是,当符号位为1,而其他域全为0时,我们得到值-0.0.根据IEEE浮点格式,值+0.0和-0.0在某些方面被认为是不同的,而在其他方面是相同的。

        非规格化数的另外一个功能就是表示哪些非常接近于0.0的数。他们提供了一种属性,称为逐渐下溢,其中,可能的数值分布均匀的接近于0.0。

情况3:特殊值

        最后一类数值是当值阶码全为1时的时候出现的。当小数域全为0时,得到的值表示无穷,当s=0时是+∞,或者当s=1时是-∞。当我们把两个非常大的数相乘,或者除以零时,无穷能够表示溢出的结果。当小数域为非零时,结果值被称为“NaN”,即“不是一个数”的缩写。一些运算的结果不能是实数或无穷,就会返回这样的“NaN”值,比如当计算\sqrt{-1} 或 ∞ - ∞ 时,在某些应用中,表示未初始化的数据时,他们也很有用处。

2.4.3 数字示例

        图 2-34 展示了一组数值,他们可以用假定的6位格式来表示,有k=3的阶码位和n=2的位数。偏置量是 2^{3-1} -1 =3 。图中的a部分显示了所有可表示的值。两个无穷值在两个末端。最大数值的规格化数是±14。非规格化数聚集在0的附近。图b部分中,我们只展示了介于-1.0和+1.0之间的数值,这样就能够看得更加清楚了。两个零是特殊的非规格化数。可以观察到,那些可表示的数并不是均匀分布的——越靠近原点处他们越稠密。

        图2-35 展示了假定的8位浮点格式的示例,其中k=4的阶码位和n=3的小数位。偏置量为2^{4-1} -1 = 7。图被分成三个区域,来描述三类数字。不同的列给出了阶码字段是如何编码阶码E的,小数字段是如何编码为数M的,以及他们一起是如何形成要表示的值V = 2^{E} * M的。从0自身开始,最靠近0的是非规格化数。这种格式的非规格化数的E=1-7 = -6,得到权 2^{E} = \frac{1}{64}。小数f的值的范围是 0,\frac{1}{8},...,\frac{7}{8},从而得到范围 0 \sim \frac{1}{64}*\frac{7}{8} = \frac{7}{512}

图2-35 8位浮点格式的非负值示例
描述位表示指数小数

eE2^{E}fM2^{E}*MV十进制
00 0000 0000-6\frac{1}{64}\frac{0}{8}\frac{0}{8}\frac{0}{512}00.0
最小的非规格化数0 0000 0010-6\frac{1}{64}\frac{1}{8}\frac{1}{8}\frac{1}{512}\frac{1}{512}0.001953
0 0000 0100-6\frac{1}{64}\frac{2}{8}\frac{2}{8}\frac{2}{512}\frac{1}{256}0.003906
0 0000 0110-6\frac{1}{64}\frac{3}{8}\frac{3}{8}\frac{3}{512}\frac{3}{512}0.005859
......
最大的非规格化数0 0000 1110-6\frac{1}{64}\frac{7}{8}\frac{7}{8}\frac{7}{512}\frac{7}{512}0.013672
最小的规格化数0 0001 0001-6\frac{1}{64}\frac{0}{8}\frac{8}{8}\frac{8}{512}\frac{1}{64}0.015625
0 0001 0011-6\frac{1}{64}\frac{1}{8}\frac{9}{8}\frac{9}{512}\frac{9}{512}0.017578
......
10 0110 1106-1\frac{1}{2}\frac{6}{8}\frac{14}{8}\frac{14}{16}\frac{7}{8}0.875
0 0110 1116-1\frac{1}{2}\frac{7}{8}\frac{15}{8}\frac{15}{16}\frac{15}{16}0.9375
0 0111 000701\frac{0}{8}\frac{8}{8}\frac{8}{8}11.0
0 0111 001701\frac{1}{8}\frac{9}{8}\frac{9}{8}\frac{9}{8}1.125
0 0111 010701\frac{2}{8}\frac{10}{8}\frac{10}{8}\frac{5}{4}1.25
......
0 1110 110147128\frac{6}{8}\frac{14}{8}\frac{1792}{8}224224.0
最大的规格化数0 1110 111147128\frac{7}{8}\frac{15}{8}\frac{1920}{8}240240.0
无穷大0 1111 000-------

        图2-36展示了一些重要的单精度和双精度浮点数表示和数字值。根据图2-35中展示的8位格式,我们能够看出有k位阶码和n位小数的浮点数表示的一般属性。

        

图2-36 非负浮点数的示例
描述expfrac单精度双精度
十进制十进制
000......000......0000.000.0
最小非规格化数00......000......012^{-23}*2^{-126}1.4*10^{-45}2^{-52}*2^{-1022}4.9*10^{-324}
最大非规格化数00......001......11\left ( 1-\varepsilon \right )*2^{-126}1.2*10^{-38}\left ( 1-\varepsilon \right )*2^{-1022}2.2*10^{-308}
最小规格化数00......010......001*2^{-126}1.2*10^{-38}1*2^{-1022}2.2*10^{-308}
101......110......001*2^{0}1.01*2^{0}1.0
最大规格化数11......101......11\left ( 2-\varepsilon \right ) *2^{127}3.4*10^{38}\left ( 2-\varepsilon \right ) *2^{1023}1.8 *10^{308}
  • 值+0.0总有一个全为0的位表示。
  • 最小的正规格化值的表示,是由最低有效位为1而其他所有位为0构成的。它具有小数(和尾数)值 M = f = 2^{-n} 和阶码值 E = -2^{k-1}+2。因此它的数字值是 V = 2^{-n-2^{k-1}+2}
  • 最大的非规格化值的位模式是由全为0的阶码字段和全为1的小数字段组成的。他有小数(和尾数)值M = f = 1-2^{-n}(我们写成1-\varepsilon)和阶码值 E = -2^{k-1}+2。因此数值 V = \left (1-2^{-n} \right ) *2^{-2^{k-1}+2},这仅比最小的规格化值小一点。
  • 最小的正规格化值的位模式的阶码字段的最低有效位为1,其他位全为0。他的尾数值M=1,而阶码值 E = - 2^{k-1}+2。因此,数值V=2^{-2^{k-1}+2}
  • 值1.0的位表示的阶码字段除了最高有效位等于0外,所有其他位都等于1。他的尾数值是 M=1,而他的阶码值是E=0。
  • 最大的规格化值的位表示的符号位时0,阶码的最低有效位等于0,其他位等于1。他的小数值f=1-2^{-n} ,尾数M=2-2^{-n}。他的阶码值E=2^{k-1}-1,得到数值  V=\left ( 2-2^{n} \right )*2^{2^{k-1}-1}  =\left ( 1-2^{-n-1} \right ) * 2^{2^{k-1}}

2.4.4 舍入

        因为表示方法限制了浮点数的范围和精度,所以浮点运算只能近似的表示实数运算。因此,对于值x,我们一般想用一种系统的方法,能够找到“最接近”比配置x,他可以用期望的浮点形式表示出来。这就是舍入运算的任务。一个关键问题是在于两个可能值的中间确定舍入方向。例如,如果我有1.50美元,想把它舍入到最接近的美元数,应该是1美元还是2美元呢?一种可选择的方法是未出实际的数字的上界和下界。例如,我们可以确定可表示的值x^{-}x^{+},使得x的值位于他们之间。IEEE浮点格式定义了四种不同的舍入方式。默认的方法是找到最接近的匹配,而其他三种可用于计算上界和下界。

        图2-37举例说明了四种舍入方式,讲一个金额数舍入到最接近的整数美元数。向偶数舍入,也被称为向最近的值舍入,是默认的方式,试图找到一个最接近的匹配值。因此,它将1.40美元舍入成1美元,而将1.6美元舍入成2美元,因为他们是最接近的整数美元值。唯一的设计决策是确定两个可能结果中间数值的舍入效果。向偶数舍入方式采用的方法是:它将数字向上或者向下舍入,是的结果的最低有效数字是偶数。因此,这种方法将1.5美元和2.5美元都舍入成2美元。

图2-37 以美元舍入为例说明舍入方式
方式1.401.601.502.50-1.50
向偶数舍入1222-2
向零舍入1112-1
向下舍入1112-2
向上舍入2223-1

        其他三种凡是产生的实际值的确界。这些方法在一些数字应用中是很有用的。向零舍入方式是把正数向下舍入,把负数向上舍入。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 深入理解计算机系统(CSAPP)是由Randal E. Bryant和David R. O'Hallaron编写的经典计算机科学教材。该教材通过涵盖计算机体系结构、机器级别表示和程序执行的概念,帮助学生深入理解计算机系统的底层工作原理和运行机制。 深入理解计算机系统的练习题对于学生巩固并应用所学知识非常有帮助。这些练习题涵盖了计算机硬件、操作系统和编译器等多个领域,旨在培养学生解决实际问题和设计高性能软件的能力。 对于深入理解计算机系统的练习题,关键是通过实践进行学习。在解答练习题时,应根据课本提供的相关知识和工具,仔细阅读问题描述,并根据实际需求设计相应的解决方案。 在解答练习题时,需要多角度思考问题。首先,应准确理解题目要求,并设计合适的算法或代码来解决问题。其次,应考虑代码的正确性和效率,以及对系统性能的影响。此外,还要注意处理一些特殊情况和异常情况,避免出现潜在的错误或安全漏洞。 解答练习题的过程中,应注重查阅相关资料和参考优秀的解答。这可以帮助我们扩展对问题的理解,并学习他人的思路和解决方法。同时,还可以通过与同学和老师的讨论,共同探讨问题和学习经验。 总之,通过解答深入理解计算机系统的练习题,可以帮助学生巩固所学知识,同时培养解决实际问题和设计高性能软件的能力。这是一个学以致用的过程,可以加深对计算机系统运行机制和底层工作原理的理解。 ### 回答2: 理解计算机系统(CSAPP)是一本经典的计算机科学教材,通过深入研究计算机系统的各个方面,包括硬件、操作系统和编程环境,对于提高计算机科学专业知识与能力具有很大帮助。 练习题是CSAPP中的重要部分,通过练习题的完成,可以加深对计算机系统的理解,并将理论知识转化为实践能力。练习题的数量、难度逐渐递增,从简单的概念与基础问题到复杂的系统设计与实现。 在解答练习题时,首先需要对题目进行仔细阅读和理解,明确题目的要求和限制条件。然后,可以利用课堂讲解、教材内容、网络资源等进行查阅和学习相应的知识。同时,还可以参考课后习题解答等资料,了解一些常见的解题方法和思路。 在解答练习题时,可以利用计算机系统的工具和环境进行实际测试和验证。例如,可以使用调试器、编译器和模拟器等工具对程序或系统进行分析和测试。这样可以更加深入地理解问题的本质,并找到恰当的解决方法。 另外,解答练习题时还可以与同学、教师和网上社区进行交流和讨论。这样可以互相学习和交流解题思路,共同解决问题。还可以了解不同的解题方法和技巧,提高解题效率和质量。 练习题的解答过程可能会遇到一些困难和挑战,例如理论知识的不足、复杂问题的分析与解决。但是通过不断地思考和实践,相信可以逐渐提高解题能力,更好地理解计算机系统。 总之,深入理解计算机系统(CSAPP)练习题是提高计算机科学专业知识和能力的重要途径。通过仔细阅读和理解题目,查阅相关知识,利用计算机系统工具和环境进行实践,与他人进行交流和讨论,相信可以更好地理解计算机系统的各个方面,并将知识转化为实际能力。 ### 回答3: 《深入理解计算机系统(CSAPP)》是计算机科学领域的经典教材之一,对于深入理解计算机系统的原理、设计和实现起到了极大的帮助。在阅读这本书的过程中,书中的习题也是非常重要的一部分,通过做习题,我们可以更好地理解书中所讲的概念和思想。 CSAPP的习题涵盖了课本中各个章节的内容,从基础的数据表示处理、程序的机器级表示、优化技术、程序的并发与并行等方面进行了深入探讨。通过解答习题,我们可以对这些知识进行实践应用,巩固自己的理解,并培养自己的解决问题的思维方式。 在解答习题时,我们需要充分理解题目要求和条件,并从知识的角度进行分析。有些习题可能需要进行一些编程实践,我们可以通过编程实现来验证和测试我们的思路和解决方案。在解答问题时,我们还可以查阅一些参考资料和网上资源,充分利用互联网的学习资源。 在解答习题时,我们需要保持积极的思维和态度。可能会遇到一些困难和挑战,但是通过坚持和努力,我们可以克服这些困难,提高我们的解决问题的能力。同时,我们还可以通过与同学或者其他人进行讨论,相互分享解题经验和思路,从而更好地理解问题。 综上所述,通过深入理解计算机系统(CSAPP)的习题,我们可以进一步巩固和深化对计算机系统的理解。掌握这些知识,不仅可以提高我们在计算机领域的能力,还可以为我们未来的学习和职业发展奠定重要的基础。因此,认真对待CSAPP的习题,是我们在学习计算机系统知识中不可或缺的一部分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值