《计算机组成原理》----2.8 浮点运算和程序员

2.8 浮点运算和程序员

整数操作是精确、可重复的。例如,在所有计算机上计算整数乘积x·y都会得到同样的结果。一台计算机上浮点单元的精度可能与另一个台上的不同,尽管IEEE浮点标准的引入已经大大改善了这一情况。

不能总是向用户隐藏浮点运算的细节(即浮点数精度以及表达式的计算方式),因为用户必须了解这些。通常,用户有关浮点的一些考虑仅会影响那些高度专用的数字应用;没有几个程序员为正在飞向火星的飞船精确地修正过路线。另一方面,有些情况下,问题本身会放大浮点误差的影响。例如,当所有卫星几乎都在线时,用GPS定位会出现因源数据的微小误差引起计算结果巨大错误的情况。

请考虑表达式z = x2 - y2,它计算两个数的平方差,这里x,y和z都是实数。可以将该表达式视作x2 - y2或(x+y)(x-y)计算。无论采用哪个表达式,整数运算都会得到同样的结果,但浮点运算却可能得到不同的值。

浮点运算是怎样进行的和这个问题有什么关系?首先请考虑x2 - y2。如果x和y的值差别很大,且x>>1,y<<1,那么相应地x2与y2的差也会很大。因此,减法x2 - y2可能产生误差,因为x2的值很大而y2的值很小。为了完成减法,应将y2的指数变大,使其与x2的指数相同。y2的尾数应右移,这会丢失一部分精度。

下面请考虑(x+y)(x-y)。这里,计算(x-y)的误差会小很多,最终的结果也精确得多。下面的8位十进制运算证明了这一点。


在进行加法之前,应使小的那个数的指数增大,使其与大的那个数的相同。为将y2的指数加7,即将它的尾数右移7位。现在就可以进行减法了。

将结果舍入到8位数字之后,可得3.5995197×105。下面按(x+y)(x-y)形式进行计算。计算(x+y)和(x-y)之前,先要将两个数的指数对齐

将结果舍入到8位数字之后,两个算式的结果分别为6.0006000×102和5.9985996× 102。这两个数的积为3.599519675976×105或3.5885197×105(舍入到8位数字后)。正如所看到的那样,这两个结果并不相同,而其原因仅仅是因为我们使用了不同计算方式。

舍入误差对计算的影响会对编译技术产生很重要的影响。例如,我们熟悉的加法结合律就不再成立了,(a+b)+c不等于a+(b+c)。如果将表达式重新排序,在同样的机器上,使用同样的数据,完成同样的计算,不同的编译器会产生不同的结果。

当进行混合精度(即单精度和双精度)计算时也会出现类似的问题。假设要计算表达式x·y+z,这里x和y是单精度值,而z为双精度。将z转换为单精度格式后,操作以单精度形式进行。不过,操作也可以双精度形式进行,但计算前要将x和y转换为双精度形式,最后还要将结果转换回单精度形式。输入误差可能使这两种方式的计算结果不同。

IEEE标准要求加、减、乘和除的运算结果能够精确计算,并用向偶数舍入的方法将结果舍入为最近的浮点数。

2.8.1 浮点运算中的误差传播

本节继续讨论浮点计算中的误差,现在来看看执行浮点计算链时会发生什么。舍入造成的生成误差(generated error)或通过计算链传播的传播误差(propagated error)都会被引入浮点运算。下面首先来看看传播误差。若Z是Y的函数,若Y的误差为ey,那么Z的误差是多少?请考虑加法操作Z = X + Y。

假设X’是计算机使用的X值,它被定义为X+Rx,这里X为真正的值而Rx为舍入带来的误差。类似的,假定Y’ = Y + Ry。X和Y的相对误差(relative error)分别被定义为Rx / X和Ry / Y。

当程序员进行操作X+Y时,计算机要完成的是X+Y+Rx+Ry。这个表达式表明,加法运算中舍入误差将会被累积。和的相对误差为(Rx+Ry)/(X+Y)。如果X和Y近似相等,相对误差就是Rx / X。

乘积X·Y将得到(X+Rx)·(Y+Ry)= X·Y+X·Ry+Y·Rx+Rx·Ry。假设误差Rx和Ry很小,因此Rx·Ry可以被忽略。舍入误差近似为X·Ry + Y·Rx。乘积的相对误差为(X·Ry + Y·Rx)/X·Y,即Ry / Y + Rx / X。若X和Y近似相等,则相对误差为2·Rx / X。注意乘法的相对误差比加法大。

多项式f(x) = a0 + a1x + a2x2 + a3x3的传播误差近似为f (1)(x)Rx,这里f (1)(x)是多项式f(x)的一阶微分。

借助多项式的泰勒级数(Taylor series),可以将多项式f(x)展开为f(x) = f(x0) + f (1)(x0)(x - x0) + f (2)(x0)(x - x0)2/2 + …。若令Rx = x - x0并假设Rx所有大于1的幂都可省略,则f(x) = f(x0) + f (1)(x0)Rx。因此,传播误差f(x) - f(x0) = f (1)(x0)Rx。请考虑计算函数2x3 + 4x2 + 3x + 2(x = 2)时的误差。这个多项式的导数为6x2 + 8x + 3,当x = 2时的计算误差约为(24 + 16 + 3)Rx = 43Rx。

两个几乎相等的数相减会引起有效位误差(Significance error)。请考虑z = x - y,这里x = 1.234567且y = 1.234521。每个操作数都有7个有效位,但结果x - y = 0.000046却只有两个有效位。假设z会被用于接下来的计算中,如p = q/z,即用只有两位有效数字的操作数完成7位有效数字的运算。程序员在用计算机进行浮点操作数必须非常小心。

2.8.2 生成数学函数

一些金融计算和绝大多数科学与工程计算都会需要比简单的加、减、乘、除更复杂的操作,如平方根、三角函数sin(x)和cos(x)、双曲函数cosh(x)等。没有必要使用专用硬件直接计算这些函数。本节将介绍如何使用基本运算实现这些高级函数。一些浮点单元确实通过基本的算术操作为部分科学计算函数提供硬件支持。

尽管本书并不是一本数学书,但还是会介绍科学函数是怎样生成的——部分是为了完整性,部分是因为其对计算机设计、算术单元和指令集的影响。任何sin(x)或那样的连续函数都可以被表示为关于参考点x0的多项式展开

f (n)(x0)定义为函数f(x)在x0处的n阶导数。这个f(x)的表达式是泰勒级数,为了计算f(x),需要将无穷多个项加在一起。但实践中,满足f(x)精度要求的项数可能很小。f(x) = sin(x)的泰勒级数为x - x3/3! + x5/5! - x7/7! + …。

将泰勒级数的前n项相加就可以得到sin(x)的值。n的值取决于后面的项以多快的速度收敛为0。有时级数收敛得很快,仅需要4或5项。有时收敛速度很慢,由于完成计算所需的时间过长而不会使用泰勒级数。

有时提供科学函数的算术单元会将生成某个特定函数所需的系数存放在只读存储器中的一张查找表(lookup table)中,以避免每次函数生成时都计算系数。例如,用泰勒级数计算sin(x)的算术单元会将系数1/3!,1/5!,等等,保存在查找表中。

实践中,对于一定范围内的x值(如计算正弦函数时x的值域为0~π/2),由泰勒级数得到的系数并不总能确保f(x)的精度最高。算术单元会使用那些对于给定的x值域能够得到更高计算精度的系数。随着变量的值接近边界,一些系数的表现将会变坏。例如,一个生成函数f(x)(0≤x≤1)的系数可能在x接近1时的逼近效果变得很差。一些系数,例如切比雪夫级数(Chebyshev series),比泰勒系数的效果更好,误差在x的值域上分布得更加均匀。与泰勒级数不同,切比雪夫级数在变量值域的边界处的误差不会很大。而且,切比雪夫级数的收敛速度比泰勒级数更快,计算近似值所需的项数也更少一些。

函数f(x)的切比雪夫级数定义为一系列切比雪夫多项式之和:

C0,C1,C2是函数f(x)的切比雪夫系数,T1(x),T2(x)是切比雪夫多项式(Chebyshev polynomials)。Tn(x)的值被定义为cos(n·acos(x)),前几项切比雪夫多项式为:

函数f(x)可以被表示为

若仅使用前6个切比雪夫多项式,该等式可写为下面的形式

对于任何需要计算的函数,如sin(x),其系数a0,a1,…的值可被保存在计算机浮点单元的只读存储器中。

本节的目的是阐明这些复杂的数学函数的来源,以及如何通过一组项求和来生成这些函数,直到获得所要求的精度。

用函数生成新的函数
没有必要使用级数或迭代技术生成科学函数。很多函数可以直接由其他函数得到。例如,e-x可由e-x = -sinh(x) + cosh(x)计算得到。sinh(x)和cosh(x)这两个双曲函数都可由浮点单元生成(使用合适的级数)。同样,我们可以通过loge(x) = 2tanh-1(x-1)/(x+1)计算自然对数。

前面已经说明,计算机可以通过各种方式间接地生成从金融到科学等各种计算中用到的数学函数。对程序员来说,重要的是实现计算的方法会影响最终答案。但对设计者来说,重要的是他们有机会设计出能够提高复杂数字函数计算速度的算术单元。

本章小结

计算机使用两个状态的二进制系统表示信息,因为这是最划算的信息表示方法。读者已经看到了如何将数字表示为有符号和无符号整数。现代计算机总是使用二进制补码表示有符号整数,因为当一个(或两个)数为负数时,减法可以通过两个二进制补码数的加法完成。

读者还看到了科学计算(例如图形学中的图着色)中浮点数的表示方法。因为浮点数并不能准确地表示实数,本章还讨论了浮点数的误差以及它们所带来的后果。本章简要讨论了计算机实现复杂数学函数(如cos和tag)的方法,解释了有很多方法可以完成这些操作,且需要在开销、速度和精度之间折中。

习题

2.1 为什么数字计算机会使用二进制算术?
2.2 我们说二进制值没有固有的含义(所有其他数据表示也是如此)。宇宙飞船旅行者I号中带有大量音乐和其他信息样本,是第一艘离开太阳系前往其他星系的人造飞船。如果数据没有固有含义,为什么可以用二进制信息进行通信?
2.3 与十进制整数运算相比,二进制整数运算有哪些不精确的地方?能否提高二进制计算机的准确度,使其与十进制计算机同样精确?
2.4 a.为什么计算机是面向字节的?

b.要获得0.001%的计算精度,需要多少位数据?

2.5 与以下数(假设它们是位置记数法的无符号整数)相等的十进制数是什么?

a. 101101112    b. 101101113    c. 101101114    d. 10110111-2

2.6 为什么要使用八进制和十六进制运算?
2.7 将下面的十进制数转换为(a)二进制(b)十六进制。

a. 36    b. 360    c. 3600    d. 36666

2.8 将下面的无符号二进制数转换为十进制。

a. 11    b. 1110    c. 11011    d. 11100110

2.9 将下面的十六进制数转换为十进制。

a. FC    b. D1C    c. 57B21    d. CCDDEE

2.10 将下面的十六进制数转换为二进制。

a. BF    b. 941D    c. 6FC01    d. DF0172

2.11 将下面的十进制小数转换为16位无符号二进制数。采用8位精度。

a. 0.6    b. 0.700164    c. 0.2331    d. 0.0876

2.12 按照要求的基数完成下面的算式。

a.  ?  001101112        b.  ?  001111112
     +111101012             +101110112
c.  ? 0012012116        d.    00ABCD1F16
    +179DC06E16             +2760FD0116

2.13 什么是算术溢出?它是怎样发生的?如何检测?
2.14 一个n位二进制补码整数N可被记作an-1an-2…a1a0。请用二进制补码表示证明,对于一个n位有符号二进制数,由其符号位和其本身可以将它表示为n+1位有符号二进制数。例如,若n = -12,用5位二进制数表示为10100,用6位二进制表示为110100。
2.15 a.将1234.125转换为32位IEEE 754浮点格式。

b. 32位IEEE浮点数CC4C0000对应的十进制数是什么?

2.16 二进制补码数上溢与浮点数上溢之间的区别是什么?
2.17 在负二进制系统中,一个i位二进制数N用位置记数法表示为:
N = a0×-10×20 + a1×-11×21 + … + ai-1×-1i-1×2i-1

这与传统的8421二进制加权自然数相同,除了额外的权值+1与-1不同。例如,1101 = (-1×1×8)+(+1×1×4)+(-1×0×2)+(+1×1×1) = -8 + 4 + 1 = -3。下面的4位二进制数被表示为负二进制形式。请将其转换为十进制。
a. 0000        b. 0101        c. 1010        d. 1111

2.18 完成以下4位负二进制数的加法运算。结果为6位负二进制数。

a. 1101        b. 1111        c. 1010        d. 0000
 ?+1011          +1111          +0101          +0001

2.19 当进行二进制补码加法运算时,若两个正数相加得到一个负数结果,或若两个负数相加得到一个正数结果,会产生算术溢出。即如果操作数A和B的符号位相同,但与结果的符号位不同,则发生了算术溢出。如果an-1为A的符号位,bn-1为B的符号位,Sn-1为A与B之和的符号位,那么溢出可被定义为

V = an-1·bn-1· + ··sn-1
实践中,真实系统在运算的最后根据Cin ≠ Cout检测溢出。即根据下式检测溢出
V = ·cn-1 + cn·
请证明该表达式是正确的。

2.20 a.截断误差与舍入误差有何不同?

b.什么是NaN数?它对浮点运算有怎样的重要性?
c.基数为13的最大三位数是多少?

2.21 计算机中有很多方法表示正数和负数。请列出一些表示有符号数的方法。你还能否想出其他一些表示有符号数的方法?
2.22 请写下最大的n位基5正整数和m位的最大基7数。要将n位基5数表示为7进制。要表示所有的n位基5数,所需m位基7数的最小位数m是多少?提示:最大m位基7数应该大于或等于最大的n位基5数。
2.23 请计算x2 - y2,这里x = 12.1234,y = 12.1111。若要进行6位有效数字(十进制)的算术运算,使用表达式x2 - y2或(x + y)(x - y)是否有必要?
2.24 计算函数x4 + x2 + 10x + 8,x = 2。如果x的误差为Rx,那么计算误差是多少?
2.25 以下ASCII码字符串的含义什么?每个字符用十六进制表示。
43,6F,6D,70,75,74,65,72,2E
2.26 为什么浮点运算很少被用于金融计算?
2.27 对于下面的,请指出它们的基数p, q, r, s, t, u分别是多少?

a. 100001p = 3310    b. 25q = 1310    c. 25r = 2310
d. 25s = 3710    e. 1010t = 6810    f. 1001u = 12610

2.28 现代计算机会使用无符号整数运算、浮点运算、二进制补码运算和浮点运算。

a. 能否从一个二进制数看出表示它的数值系统?
b. 为什么有这么多表示数值的方法?
c. 我们是否需要所有这些机制?

2.29 一个数字逻辑元件用2.8~2.95V电压间的输出表示高状态。相同的逻辑元件在2.1~3.0V电压范围内的输入为高状态。为什么会有这样的不同?它有何实践意义?
2.30 请给出图P2.30中电路的中间值和输出值的真值表。

时间: 2024-10-27 20:41:50

《计算机组成原理》----2.8 浮点运算和程序员的相关文章

程序员谈如何掌握计算机专业英语

转自:http://www.kuqin.com/english/20080512/8356.html  (准备写篇相似的东西,看到这篇比较早的文章,很有启发.)   干程序员是一项很辛苦的工作,要成为一个高水平的程序员尤为艰难.这是因为计算机软件技术更新的速度越来越快,而这些技术大多来源于英语国家,我们在引进这些技术时往往受到语言障碍的制约,严重影响到对新技术的理解和消化.首先编程本身就依赖于英语,虽然现在技术的发展,可以使得某些开发工具在变量名和字段名中支持中文,但还未发现能够完全使用中文的编

计算机爱好者与程序员的区别

导读:本文是从<Hackers vs. Coders>这篇文章翻译而来.译文来自外刊IT评论整理编译<计算机爱好者 VS. 程序员>.文中简单介绍了程序员和计算机爱好者之前的区别. 以下是文章内容: 优秀的计算机爱好者具有一种无价的技能.可作为一名程序员会跟计算机爱好者一样吗?难道程序员跟那些不知道如何编码的计算机爱好者们相比,会在创造性上处于劣势吗? 下面的这个故事让我看清了他们之间的不同. 我最近被邀请在一个周末创业活动中做指导.周五晚上,我们召集到一起吃匹萨,定创意,建团队以

《计算机组成原理》----导读

目 录 第一部分 起始篇第1章 计算机系统体系结构1.1 什么是计算机系统体系结构1.2 体系结构和组成1.2.1 计算机系统和技术1.2.2 计算机体系结构在计算机科学中的地位1.3 计算机的发展1.3.1 机械计算机1.3.2 机电式计算机1.3.3 早期的电子计算机1.3.4 微机和PC革命1.3.5 摩尔定律和进步的历程1.3.6 存储技术发展1.3.7 普适计算1.3.8 多媒体计算机1.4 存储程序计算机1.4.1 问题描述1.4.2 解决方法1.4.3 构造一个算法1.4.4 计算

为什么程序员的社会地位不高?

到目前为止,在过去60年中在世界排名前20的国家中,没有哪条街是以程序员或者计算机科学家的名字命名的.没有任何一个世界主要城市拥有程序员或者计算机科学家的雕像.没有程序员或者计算机科学家获得过总统奖章(Presidential Medal)或者国会金质奖章(Congressional Gold Medal).没有国家级别的针对程序员或者计算机科学家的颁奖典礼. 但是我们有艺术.运动.经济.娱乐等大型颁奖典礼.更没有红地毯或者类似诺贝尔奖来表彰程序员的成就和为人类作出的贡献. 即使程序员.计算机科

程序员成长规划

引言 我的程序员成长之路 程序员的成长经历往往很相似,大部分的人走过了最前面相同的一段路,而有的人则走得更远.总结自己这些年来的历程,这也许能让年轻的程序员少走一些弯路,成长得更快:或许更好一些,能让大家从中得到一些启发,早日进入优秀程序员的阶段,实现梦想,释放激情. 第一阶段,最初是在学校里学习计算机基础知识,学习经典的程序设计语言,编写测试用的小程序.这个过程可以说是对计算机和程序设计的入门阶段.这个阶段主要是培养了自己对计算机软件的兴趣,打下了良好的计算机基础知识. 第二阶段,而后参加工作

[转]程序员资料整理

前言 一些主流技术资源整理. 目录 资料篇 技术站点 必看书籍 大牛博客 GitHub篇 工具篇 平台工具 常用工具 第三方服务 爬虫相关(好玩的工具) 安全相关 Web服务器性能/压力测试工具/负载均衡器 大数据处理/数据分析/分布式工具 Web前端 语言篇 Scala Java Python Swift .NET C & C++ 其他 游戏开发相关 日志聚合,分布式日志收集 RTP,实时传输协议与音视频 资料篇 技术站点 在线学习:Coursera.edX.Udacity.MIT公开课.MO

程序员必读书单(转)

  原文链接:http://lucida.me/blog/developer-reading-list/ 关于 本文把程序员所需掌握的关键知识总结为三大类19个关键概念,然后给出了掌握每个关键概念所需的入门书籍,必读书籍,以及延伸阅读.旨在成为最好最全面的程序员必读书单. 前言 Reading makes a full man; conference a ready man; and writing an exact man. Francis Bacon 优秀的程序员应该具备两方面能力: 良好的

程序员必读书单

关于 本文把程序员所需掌握的关键知识总结为三大类19个关键概念,然后给出了掌握每个关键概念所需的入门书籍,必读书籍,以及延伸阅读.旨在成为最好最全面的程序员必读书单. 前言 Reading makes a full man; conference a ready man; and writing an exact man. Francis Bacon 优秀的程序员应该具备两方面能力: 良好的程序设计能力: 掌握常用的数据结构和算法(例如链表,栈,堆,队列,排序和散列): 理解计算机科学的核心概念

《计算机组成原理》----1.2 体系结构和组成

1.2 体系结构和组成 我们已经建立起计算机和系统这两个概念,我们还必须单独定义术语体系结构.计算机体系结构含有结构(structure)的意思,描述了一些与计算机组成方式有关的内容.之所以定义计算机体系结构,是因为不同的用户会从完全不同的角度看待计算机.例如,秘书可能会将计算机视作一个聪明的字处理设备,而物理学家可能会将它看作是晶体中电子的活动. 我们对这两种极端的观点都不感兴趣.计算机体系结构通常被认为是程序员视角中的计算机.程序员所看到的是计算机的抽象视图,对他们来说,计算机的实际硬件和实