《浮点转定点方法总结》由会员分享,可在线阅读,更多相关《浮点转定点方法总结(19页珍藏版)》请在金锄头文库上搜索。
1、浮点转定点方法总结孔德琦目录定点运算方法31.1 数 的 定 标31.2c语言:从浮点到定点41.2.1 加法41.2.2乘法61.2.3除法71.2.4 三角函数运算81.2.5 开方运算91.3 附录101.3.1 附录1:定点函数库101.3.2附录2:正弦和余弦表28定点运算方法1.1 数 的 定 标对某些处理器而言,参与数值运算的数就是16位的整型数。但在许多情况下,数学运算过程中的数不一定都是整数。那么,如何处理小数的呢?应该说,处理器本身无能为力。那么是不是就不能处理各种小数呢?当然不是。这其中的关键就是由程序员来确定一个数的小数点处于16位中的哪一位。这就是数的定标。通过设定小
2、数点在16位数中的不同位置,就可以表示不同大小和不同精度的小数了。数的定标用Q表示法。表1.1列出了一个16位数的16种Q表示能表示的十进制数值范围和近似的精度。Q表示精度(近似)十进制数表示范围Q150.00002-1X0.9999695Q140.00005-2X1.9999390Q130.0001-4X3.9998779Q120.0002-8X7.9997559Q110.0005-16X15.9995117Q100.001-32X31.9990234Q90.002-64X63.9980469Q80.005-128X127.9960938Q70.01-256X255.9921875Q60.0
3、2-512X511.9804375Q50.04-1024X1023.96875Q40.08-2048X2047.9375Q30.1-4096X4095.875Q20.25-8192X8191.75Q10.5-16384X16383.5Q01-32768X32767表1.1 Q表示、S表示及数值范围从表1.1可以看出,同样一个16位数,若小数点设定的位置不同,它所表示的数也就不同。例如:16进制数2000H8192,用Q0表示16进制数2000H0.25,用Q15表示从表1.1还可以看出,不同的Q所表示的数不仅范围不同,而且精度也不相同。Q越大,数值范围越小,但精度越高;相反,Q越小,数值范围越
4、大,但精度就越低。例如,Q0的数值范围是-32768到+32767,其精度为1,而Q15的数值范围为-1到0.9999695,精度为 1/32768 = 0.00003051。因此,对定点数而言,数值范围与精度是一对矛盾,一个变量要想能够表示比较大的数值范围,必须以牺牲精度为代价;而想提高精度,则数的表示范围就相应地减小。在实际的定点算法中,为了达到最佳的性能,必须充分考虑到这一点。浮点数与定点数的转换关系可表示为:浮点数(x)转换为定点数():定点数()转换为浮点数(x):例如,浮点数 x=0.5,定标 Q15,则定点数,式中表示下取整。反之,一个用 Q15 表示的定点数16384,其浮点数
5、为163842-1516384/32768=0.5。1.2 c语言:从浮点到定点下面所描述的几种基本运算是浮点到定点转换中经常遇到的,从中可以体会到一些基本的技巧和方法。1.2.1 加法设浮点加法运算的表达式为:float x,y,z;z=x+y;将浮点加法/减法转化为定点加法/减法时最重要的一点就是必须保证两个操作数的定标值一样。若两者不一样,则在做加法/减法运算前先进行小数点的调整。为保证运算精度,需使Q值小的数调整为与另一个数的Q值一样大。此外,在做加法/减法运算时,必须注意结果可能会超过16位表示,即数的动态范围。如果加法/减法的结果超出16位的表示范围,则必须保留32位结果,以保证运
6、算的精度。1 结果不超过16位表示范围设x的Q值为Qx,y的Q值为Qy,且QxQy,加法/减法结果z的定标值为Qz,则zx+y = 一般情况,我们取x,y和z的定标值相同,即Qx = Qy = Qz = Qa 。所以定点加法可以描述为: short x, y, z ; /Qa z = add (x,y); /Qa函数add ( ) 有防饱和机制,如果可以确信x + y 不会溢出(-215 = z = 215-1),可以直接写为 z = x + y .定点减法:short x, y, z ; /Qaz = sub (x,y); /Qa函数sub ( ) 有防饱和机制,如果可以确信x - y 不会
7、溢出(-215 = z Qy,加法结果z的定标值为Qz,则定点加法为:int x,y;long temp,z;tempy(Qx-Qz),若QxQzztemp(Qz-Qx),若QxQz一般情况,我们取x,y和z的定标值相同,即Qx = Qy = Qz = Qa 。所以定点加法可以描述为: int x, y, z ; /Qa z = L_add (x,y); /Qa函数L_add ( ) 有防饱和机制,如果可以确信x + y 不会溢出(-231 = z = 231-1),可以直接写为 z = x + y .定点减法: int x, y, z ; /Qa z = L_sub (x,y); /Qa函数
8、L_sub ( ) 有防饱和机制,如果可以确信x - y 不会溢出(-231 = z (Qx+Qy+1-Qz);上式中x乘y的定标本来应该是Qx + Qy, 但为了处理方便,函数L_mult( ) 多乘了一次2,因此要再加1。函数L_mult ( ) 有防饱和机制,如果可以确信z = x y 不会溢出(-231 = z (Qx+Qy-Qz)。2. 结果超过32位表示范围这种情况下位数超出了标准c语言的数的表示范围,只能用数组来保存变量。定点乘法可表示为:#define NN_DIGIT unsigned int NN_DIGIT x digits; NN_DIGIT y digits; NN_
9、DIGIT z 2* digits; NN_Mult (z, x, y, digits);应注意的是以上32位乘法都是无符号数操作,如果需要做有符号数乘法,则需要根据乘数的符号来判断。例1 设x = 18.4,y = 36.8,则浮点运算值为z =18.436.8 = 677.12;设 Qx = 10,Qy = 9,Qz = 5,所以int x = 18841;/Q10int y = 18841;/Q9z = L_mult(18841, 18841)(10+9+1-5) = 354983281L14 = 21666;因为z的定标值为5,故定点 z = 21666即为浮点的 z = 21666/
10、32 = 677.08。例2设x = 18.4,y = 36.8,则浮点运算值为z =18.436.8 = 677.12;#define NN_DIGIT unsigned int设Qx = 20, Qy = 20, Qy = 20, 所以NN_DIGIT x = 18.4 * (120); /Q20NN_DIGIT y = 36.8 * (120); /Q20NN_DIGIT z2; /Q20NN_Mult(z, &x, &y, 1); /Q40NN_Rshift(z, z, 20, 1); /Q(40-20)1.2.3除法1. 32位除法设浮点除法运算的表达式为:float x,y,z;z
11、 = x/y;假设经过统计后被除数x的定标值为Qx,除数y的定标值为Qy,商z的定标值为Qz,则z = x/y = 所以定点表示的除法为:int x,y,z;z = L_shl(x, (Qz-Qx+Qy) )/y; /Qz2. 32位以上的除法这种情况下位数超出了标准c语言的数的表示范围,只能用数组来保存变量。#define NN_DIGIT unsigned intNN_DIGIT x 2*digits; /QxNN_DIGIT y digits; /QyNN_DIGIT z digits; /QzNN_Lshift(x, x, (Qz-Qx+Qy), 2);NN_Div(z, x, 2*d
12、igits, y, digits); 做以上运算是要保证Qz-Qx+Qy 32, 否则要多次移位来实现;应注意的是以上除法都是无符号数操作,如果需要做有符号数除法,需要根据被除数和除数的符号来判断。例 1: 设x = 18.4,y = 36.8,浮点运算值为z = x/y = 18.4/36.8 = 0.5;根据上节,得Qx = 10,Qy = 9,Qz = 15;所以有int x = 18841, y = 18841;z = L_shl(x, (15-10+9) )/18841; / 308690944L/18841 = 16384因为商z的定标值为15,所以定点z = 16384即为浮点 z = 16384/215= 0.5。1.2.4 三角函数运算1 正弦和余弦一般求cos、sin用查表法,方法是预先定义