英语原文共 666 页,剩余内容已隐藏,支付完成后下载完整资料
第4章 DSP软件
DSP应用程序通常使用与其他科学和工程领域中相同的语言(如C语言、BBASIC和汇编)来编写。C语言的强大功能和通用性使它成为计算机科学家和其他专业程序员所选择的语言。另一方面,BASIC的简单性也使它成为不经常编程的科学家和工程师们的理想选择,而无论你使用什么语言,大部分的重要DSP软件问题都深藏在告诉运行的1和0的世界里。本章包括的主题有:如何用二进制位模式表示数字,计算机计算中的舍入误差,不同类型处理器的计算速度等。简而言之,本章讨论的内容有助于你做好高层的工作,避免计算机发生地层内部错误。
4.1 计算机的数
数字计算机在储存和恢复数字方面非常专业,不幸的是,这一过程并非没有误差。举例来说,你指示计算机储存数字1.414 213 56,计算机尽力储存它能表示的最接近的数字:1.414 213 54.这个误差在一些情况下是无关紧要的,而在其他情况下,则是灾难性的。再举一个例子,例如常见的由两个差值很大的数相加产生的计算误差,比如说,1和0.000 000 01。我们想要的答案是1.000 000 01,但是计算机回答1.理解计算机如何储存和处理数字可以让你在程序给出没有意义的数据之前预见和改正这些问题。
出现这些问题是由于分配了一个固定位数(通常为8位、16位、32位、或64位)的空间来储存每个数字。举例来说,考虑用8位的空间来储存变量的值。因为有256种可能的组合,故变量只能表示256种不同的值。这是基本限制,而且我们无法改善。我们能控制的只是每种位组合所代表的数值。最简单的情况是,这256个位序列可代表从0到256个指数相关的数字:1,10,100,1000,...。存取数据的人员必须了解每个位序列代表什么样的数值。这通常由一个用于在数值和对应的位序列之间双向转换的算法或公式来完成。
尽管许多编码方式都是可行的,但只有两种格式是通用的,定点(也称为整数)和浮点(也称为实数)。在这本书的BASIC程序中,定点变量由百分号%符号作为名称的最后一个字符,比如I%,N%,SNU%等;而所有其他形式的变量是浮点型的,比如说X,Y,MEAN等。当你计算后面几页中出现的格式的值时,请尝试着从范围(它们能变现的最大值和最小值)和精度(数字之间的间隔)两方面来理解它们。
4.2 定点(整数)
定点表示法用来储存整数,包括所有的正负整数:-3,-2,-1,0,1,2,3,...。高级编程,比如说C语言和BASIC,通常分配16位去储存个整数。最简单的情况,65 536个可能的位序列分配给数字0到65 535,称做无符号整数,如图4-1中的简例(每个数字只用4位)。位组合与其代表的数字之间的转换其实只不过是二进制和十进制之间的转换。无符号整数的缺点是不能表示负数。
偏移二进制是除了通过移位十进制数表示负数之外,与无符号整数类似的另一种表示法。在图4-1的4位例子中,十进制数偏移7位,使得16个位序列分别对应整数-7到8。以相同的方式,16位表示法将会以32 767为偏移量,从而其范围在-32 767和32 768之间。偏移二进制不是一个标准化的格式,而且你将发现其他的偏移量在使用,如32 768。偏移二进制的最重要的应用在于模数转换和数模转换。比如,输入电压范围是从-5至5V,对于一个12位的转换,可能被映射到数字0到4 095。
符号加数值是表示负数的另一种表示方法。最左边的-位叫做符号位,0代表正数,1表示负数。其他位是数字绝对值的标准二进制表示。请注意这将造成一个位序列的浪费,因为有两个表示零的方法,0000(正零)和1000(负零)。这种编码方式形成16 位数的范围是-32767到32767。
前3种表示法的概念很简单,但是在硬件中实现很困难。要知道,当A=B C被输入到计算机程序中,硬件工程师必须解决该如何用表示B的位序列加上表示的C的位序列,形成表示A的位序列。
补码是硬件工程师喜爱的格式,也是在计算机中表示整数的格式。要了解编码方式,首先要了解在图4-1中对应二进制零000的十进制的零。当我们计数时,十进制数字就是简单的二进制等价(0=0000,1=0001,2=0010,3=0011等)。现在要记住,这4位被储存在由4个触发器组成的寄存器中。如果我们再一次从零 0000开始做减法,数字硬件会自动地以补码计数计算0-0000, -1-1111, -2=1110, -3=1101等。这就像是一辆新汽车的里程表。如果受到驱动是向前的,它以这样的顺序改变: 0000, 0001, 0002 0003等。当受到驱动是向后的,里程表改变: 0000, 9999, 9998, 99979 等。
使用16位补码能表示的数字从-32 768到32 767。如果数字是正的或零,则最左边的一位是零,如果数字是负的则是一。相应地,最左边的一位叫做符号位,就像是符号加数值表示法。对于正数,十进制和补码可以直接转换,其实就是一种简单的十进制与二进制转换。对负數而言,通常使用下列运算法则:
(1)取十进制数的绝对值;
(2)将它转换成二进制;
(3)取所有位的补码(1 变0, 0变1);
(4)对二进制数加一。
例如-5→5→0101→1010→1011.补码对人来说很难,但是对数字电子却非常简单。
4.3 浮点(实数)
对于浮点的编码方案比定点更复杂。其基本思想同科学计数法(即尾数乘以10的指数幂)相同。例如,5.4321x10, 5.432 1是尾数和6是指数。科学的计数法适合于表示非常大的和非常小的数字。即地球上原子的数目,即海龟在1s内爬行的距离与银河系的直径之比。注意到科学计数法中数字表现是被标准化的,以至小数点的左边只有一个非零数字。这通过按需要调整指数完成。
浮点表示法除了-切都基于二进制而非十进制以外,与科学计数法还是很类似的。有数种相似格式可供使用,最常用的是ANSIIEEE标准754-1985。该标准定义的32位的格式称为单精度,64位称为双精度。如图4-2所示,单精度中使用的32位被分为3部分: 0到22位构成尾数,23 到30位构成指数,31 位是符号位。这些位通过以下关系构成浮点数v:
式(4-1)位序列转换为浮点数的公式。浮点数用v表示,S是符号位的值,M是尾数的值,而E是指数的值。
式(4-1)中的项表示符号位,S为0代表正数,为1代表负数。变量E是由8个指数位表示的0和255之间的数。将这个数减去127可以使指数项的范围变为2-127到2128。换句话说,说明指数项是以偏移量为127的偏移进制形式存储的。
尾数M是由23位构成的进制小数。例如,十进制的小數2.783,可以被描述为2 7/10 8/100 3/1 000。二进制小數1.010 1可看作1 0/2 1/4 0/8 1/16.浮点数同科学计数法一样是标准化的,即小数点左边只有一个非零数字(称为基于2的二进制小数点)。既然基于2的非零数字只有1,因此尾数第1位数字总是1, 所以不需要存储。移除此冗余位所腾出的空间可使数字相应提高1位精度。这23个存储位:形成的尾数如式(4-2)所示
换句话说,若位0到22全为0, M即为1。若位0到22全是1,那么M只比2小一点,
使用这种编码方案,可以表示的最大数字是:能表示的最小数字是:IEEE标准稍微减小了这一区间,空出一些位序列用于表示特殊意义。特别需要注意的是,该标准里允许的最大和最小的数字分别是那些空出的位组合可以表示3类特殊的数字:表示尾数和指数的所有位均为0;表示尾数的所有位都是0,并且指数的所有位均是1;处于之间的一组非常小的未标准化的数字。这些数字精度较低,因为除去了尾數中第位必须是1的要求。除这3种特例之外,还有一些位序列没被分配意义,通常称为NAN(非數字)。
IEEE的双精度标准只是简单地在尾数和指數部分都增加了一些位。在储存双精度数字的64位中,0到51位是尾数,52到62位是指数,63位是符号位。跟前面一样,尾数在1到2之间,比2稍小一点。11个指数位可表示一个位于0到2047之间,且偏移量为1 023的数字,其指数范围在2102到2104之间。双精度表示法允许的最大和最小的数字分别是到这是相当大和相当小的数字!很难找到种双精度不够精确的应用。你或许永远不会找到-种双精度受限制的情况。
4.4 数字精度
数字表示法的误差同模数转换的量化误差非常相似。尽管你想要储存一些连续的值,然而你只能表示有限个量化级别数字。每次产生-个新数字时(如在一-次数学计算之后),它定会被四舍五入成所用格式中能够储存的最接近值。
举个例子,假如你要分配32位去储存一个数字。因为有232 = 4294 967 296种可能的位序列,能够表示4 294967 296个不同的数字。有一些编程语言允许使用一种叫做长整型的变量,以32位、定点、补码的形式存储。这意味着有4294967296个可能的位序列表示从-2 147 483 648到2 147 483 647之间的整数。比较而言,单精度浮点把4 294 967 296个位序列分布在更大的范围内:-3.4*1038到3.4*1038。
定点变量,相邻数字的间隔总是准确的1。而浮点计数法相邻数字的间隔会根据所表示数字的范围而改变。如果我们任意找个浮点数,与相邻数字的间隔大约是数字本身的一千万分之一(精确表示,为2-24倍到2-13倍)。浮点计数法的关键概念是:大的数字有较大的间距而小的数字有较小的间距。如图4-3所示的连续浮点数和它们的间距说明了这一点。
表4-1的程序举例说明了舍入误差如何在DSP中引|起问题(数学计算中的量化误差)。在程序循环中,浮点变量X先加上两个随机数,然后又将其减去。在理想的情况下,应该相当于什么也没有做。事实上,每次数学计算产生的舍人误差使X值渐渐地偏离了其原始值。这种偏离究竟是两种形式中的哪种取决于误差如何累积。如果舍入误差是正负随机出现的,变量值也会随机地增加和减少。如果误差是由同-种符号占主导,变量数值就会偏离得更快速且具单向性。
图4-4显示了示例程序中变量X的值是如何偏离的。一个明显的问题是加性误差比随机误差更加严重。这是因为随机误差互相之间容易抵消,而加性误差只是单调累积。加性误差大概等于单步操作中的舍人误差乘以总的操作数。相比之下,随机误差仅随运算次数的平方根成比例增加。如本例所示,对于普通的DSP运算而言,加性误差比随机误差要严重数百倍。
不幸的是,想要控制或者预测-一个特定的运算中将会发生哪种行为几乎是不可能的。比如,表4-1的程序产生了-个加性误差。仅需稍微修改所加减的数字就可以将这个加性误差转变为随机误差。特别地,图4-4中的随机误差曲线产生于如下定义: A=EXP(RND)和B=EXP(RND),而不是A=RND和B=RND。使得A和B的值指数性分布在1和2.718之间,而非在0到:1之间随机分布。即使如此-个小小的变化却足以改变误差的累积方式。
虽然我们不能控制舍入误差的累积方式,但要估计出最坏的情况。每个单精度数会有四千万分之一的误差,乘以数宇历经的操作数。这是基于加性误差的假设,单精度运算的平均误差是量化水平的四分之一。通过相同的分析,可以看出每一一个双精度数字有四十亿分之一的误差,由操作数相乘而得。
表4-2展示了一个舍入误差中令人特别烦恼的问题。表中的两个程序完成相同的任务:输出1001个在0和10之间等距分布的数。左侧的程序使用浮点变量X作为循环指数。当程序开始运行时,计算机都要设定循环指数的初始值(本例为0)。在每个循环周期的结尾给循环指数加上步长(本例中为0.01)。 这时需要做一个决定:是进行更多的循环,还是结束循环?当计算机发现循环指数比终值(本例中为10.0)大时,循环即告结束。如产生的输出结果所示,加法中的舍人误差导致x的值在循环的过程中累积了一个明显的偏差。事实上,累积的误差阻止了最后一个循环周期的执行。因为在最后一个周期,误差使X的值为10.000 133而不是10.0。因为x大于终值,计算机觉得它的任务已经完成,所以循环提前结束。丢失最后的值是许多计算机程序的常见缺陷。
比较之下,右边的程序用了一个整型变量I%来控制循环。两个整数的加法、减法或乘法总会产生另外一个整数。这意味着定点计数法经过这些操作肯定没有舍人误差。同其他经过多次数学运算的变量-样,用整数来控制循环是理想的。能保证最后一个循环周期得以执行!最好总是用整数来做循环指数和计数,除非你有一些不得已的理由要用其他的。
如果必须使用浮点变量做循环指數,推荐使用分母为2的整数幂的分数对应的小数(如12、14、3/8. 27/16),而不是分母为10的整数幂的分数所对应的小数(如0.1.、0.6、1.4、2.3等)。举例来说,最好用FORX= 1to 10 STEP 0.125,而不是FORX= 1to 10 STEP0.1.这样指数总能够有一个精确的二进制表示值,因此可以减少舍人误差。比如说,十进制的数字1.125,可以精确地用二进制表示为相比之下,十进制数1.1在两个浮点数字之间:这造成程序每次遇到1.1就会产生一个固有误差。
要记住一个有用的事实:在之间的每一个单精度浮点数都有一一个精确的二进制表示式。如果超出此范围,相邻数字的间距比I大,会造成些整数值的丢失。这样浮点数(在百万之间)之间就可以无舍人误差地进行加法、减法及乘法运算。
4.5 执行速度:程序语言<br
剩余内容已隐藏,支付完成后下载完整资料</br
资料编号:[608842],资料为PDF文档或Word文档,PDF文档可免费转换为Word
课题毕业论文、外文翻译、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。