浮点转定点方法总结.docx
《浮点转定点方法总结.docx》由会员分享,可在线阅读,更多相关《浮点转定点方法总结.docx(26页珍藏版)》请在冰豆网上搜索。
浮点转定点方法总结
浮点转定点方法总结
CIITechnologies,Inc.浮点转定点方法总结
浮点转定点方法总结
—孔德琦
1
CIITechnologies,Inc.目录
定点运算方法...................................................................................................................................31.1数的定标...........................................................................................................................3
1.2C语言:
从浮点到定点....................................................................................................4
1.2.1加法.................................................................................................................................4
1.2.2乘法..................................................................................................................................6
1.2.3除法..................................................................................................................................7
1.2.4三角函数运算.................................................................................................................8
1.2.5开方运算.........................................................................................................................91.3附录......................................................................................................................................10
1.3.1附录1:
定点函数库....................................................................................................10
1.3.2附录2:
正弦和余弦表.................................................................................................19
2
CIITechnologies,Inc.浮点转定点方法总结
定点运算方法
1.1数的定标
对某些处理器而言,参与数值运算的数就是16位的整型数。
但在许多情况下,数学运算过程中的数不一定都是整数。
那么,如何处理小数的呢,应该说,处理器本身无能为力。
那么是不是就不能处理各种小数呢,当然不是。
这其中的关键就是由程序员来确定一个数的小数点处于16位中的哪一位。
这就是数的定标。
通过设定小数点在16位数中的不同位置,就可以表示不同大小和不同精度的小数了。
数的定标用Q表示法。
表1.1列出了一个16位数的16种Q表示能表示的十进制数值范围和近似的精度。
Q表示精度(近似)十进制数表示范围
Q150.00002-1?
X?
0.9999695
Q140.00005-2?
X?
1.9999390
Q130.0001-4?
X?
3.9998779
Q120.0002-8?
X?
7.9997559
Q110.0005-16?
X?
15.9995117
Q100.001-32?
X?
31.9990234
Q90.002-64?
X?
63.9980469
Q80.005-128?
X?
127.9960938
Q70.01-256?
X?
255.9921875
Q60.02-512?
X?
511.9804375
Q50.04-1024?
X?
1023.96875
Q40.08-2048?
X?
2047.9375
Q30.1-4096?
X?
4095.875
Q20.25-8192?
X?
8191.75
Q10.5-16384?
X?
16383.5
Q01-32768?
X?
32767
表1.1Q表示、S表示及数值范围
从表1.1可以看出,同样一个16位数,若小数点设定的位置不同,它所表示的数也就不同。
例如:
16进制数2000H,8192,用Q0表示
16进制数2000H,0.25,用Q15表示
从表1.1还可以看出,不同的Q所表示的数不仅范围不同,而且精度也不相同。
Q越大,数值范围越小,但精度越高;相反,Q越小,数值范围越大,但精度就越低。
例如,Q0的数值范围是-32768到+32767,其精度为1,而Q15的数值范围为-1到0.9999695,精度为
3
CIITechnologies,Inc.浮点转定点方法总结
1/32768=0.00003051。
因此,对定点数而言,数值范围与精度是一对矛盾,一个变量要想能够表示比较大的数值范围,必须以牺牲精度为代价;而想提高精度,则数的表示范围就相应地减小。
在实际的定点算法中,为了达到最佳的性能,必须充分考虑到这一点。
浮点数与定点数的转换关系可表示为:
Qx,(int)x,2x浮点数(x)转换为定点数():
qq
Qxx,(float)x,2定点数()转换为浮点数(x):
qq
x,,式中表示例如,浮点数x=0.5,定标Q,15,则定点数0.5,32768,16384q,,,,
-15下取整。
反之,一个用Q,15表示的定点数16384,其浮点数为16384×2,16384/32768=0.5。
1.2c语言:
从浮点到定点
下面所描述的几种基本运算是浮点到定点转换中经常遇到的,从中可以体会到一些基本的技巧和方法。
1.2.1加法
设浮点加法运算的表达式为:
floatx,y,z;
z=x+y;
将浮点加法/减法转化为定点加法/减法时最重要的一点就是必须保证两个操作数的定标值一样。
若两者不一样,则在做加法/减法运算前先进行小数点的调整。
为保证运算精度,需使Q值小的数调整为与另一个数的Q值一样大。
此外,在做加法/减法运算时,必须注意结果可能会超过16位表示,即数的动态范围。
如果加法/减法的结果超出16位的表示范围,则必须保留32位结果,以保证运算的精度。
1(结果不超过16位表示范围
设x的Q值为Qx,y的Q值为Qy,且Qx>Qy,加法/减法结果z的定标值为Qz,则
z,x+y,
Q,Q,Qyxzz,2,x,2,y,2qqq
()Q,Q,Q,Qxyxxx,2,y,2,2=qq
()Q,Q,Qxyx[x,y,2],2=,qq
(Q,Q)(Q,Q)xyzxz,[x,y,2],2qqq
一般情况,我们取x,y和z的定标值相同,即Qx=Qy=Qz=Qa。
所以定点加法可以描述为:
shortx,y,z;//Qa
z=add(x,y);//Qa
4
CIITechnologies,Inc.浮点转定点方法总结
函数add()有防饱和机制,如果可以确信x+y不会溢出(-2^15<=z<=2^15-1),可以直接写为z=x+y.
定点减法:
shortx,y,z;//Qa
z=sub(x,y);//Qa
函数sub()有防饱和机制,如果可以确信x-y不会溢出(-2^15<=z<=2^15-1),可以直接写为z=x-y.
2(结果超过16位表示范围
设x的Q值为Qx,y的Q值为Qy,且Qx>Qy,加法结果z的定标值为Qz,则定点加法为:
intx,y;
longtemp,z;
temp,y<<(Qx-Qy);
temp,x,temp;
z,temp>>(Qx-Qz),若Qx?
Qz
z,temp<<(Qz-Qx),若Qx?
Qz
一般情况,我们取x,y和z的定标值相同,即Qx=Qy=Qz=Qa。
所以定点加法可以描述为:
intx,y,z;//Qa
z=L_add(x,y);//Qa
函数L_add()有防饱和机制,如果可以确信x+y不会溢出(-2^31<=z<=2^31-1),可以直接写为z=x+y.
定点减法:
intx,y,z;//Qa
z=L_sub(x,y);//Qa
函数L_sub()有防饱和机制,如果可以确信x-y不会溢出(-2^31<=z<=2^31-1),可以直接写为z=x-y.
3.结果超过32位表示范围
这种情况下位数超出了标准c语言的数的表示范围,只能用数组来保存变量。
定点加法可以描述为:
#defineNN_DIGITunsignedint
NN_DIGITx[digits],y[digits],z[digits];//Qa
NN_Add(z,x,y,digits);//Qa
定点减法:
5
CIITechnologies,Inc.浮点转定点方法总结
NN_DIGITx[digits],y[digits],z[digits];//Qa
NN_Sub(z,x,y,digits);Qa
应注意的是以上32位定点加减法都是无符号数操作。
1.2.2乘法
1(16位乘法
设浮点乘法运算的表达式为:
floatx,y,z;
z=xy;
假设经过统计后x的定标值为Qx,y的定标值为Qy,乘积z的定标值为Qz,则
z=xy,
(Q,Q),Qxyzz,2x,y,2=,qqq
Q,(Q,Q)zxyz(xy)2=qqq
所以定点表示的乘法为:
shortx;//Qx
shorty;//Qy
intz;//Qz
z=L_mult(x,y)>>(Qx+Qy+1-Qz);
上式中x乘y的定标本来应该是Qx+Qy,但为了处理方便,函数L_mult()多乘了一次2,因此要再加1。
函数L_mult()有防饱和机制,如果可以确信z=xy不会溢出(-2^31<=z<=2^31-1),可以直接写为z=(xy)>>(Qx+Qy-Qz)。
2.结果超过32位表示范围
这种情况下位数超出了标准c语言的数的表示范围,只能用数组来保存变量。
定点乘法可表示为:
#defineNN_DIGITunsignedint
NN_DIGITx[digits];
NN_DIGITy[digits];
NN_DIGITz[2*digits];
NN_Mult(z,x,y,digits);
应注意的是以上32位乘法都是无符号数操作,如果需要做有符号数乘法,则需要根据乘数的符号来判断。
例1
设x=18.4,y=36.8,则浮点运算值为z=18.4×36.8=677.12;
设Qx=10,Qy=9,Qz=5,所以
intx=18841;//Q10
inty=18841;//Q9
z=L_mult(18841,18841)>>(10+9+1-5)=354983281L>>14=21666;
因为z的定标值为5,故定点z=21666即为浮点的z=21666/32=677.08。
例2
6
CIITechnologies,Inc.浮点转定点方法总结
设x=18.4,y=36.8,则浮点运算值为z=18.4×36.8=677.12;
#defineNN_DIGITunsignedint
设Qx=20,Qy=20,Qy=20,所以
NN_DIGITx=18.4*(1<<20);//Q20
NN_DIGITy=36.8*(1<<20);//Q20
NN_DIGITz[2];//Q20
NN_Mult(z,&x,&y,1);//Q40
NN_Rshift(z,z,20,1);//Q(40-20)1.2.3除法
1.32位除法
设浮点除法运算的表达式为:
floatx,y,z;
z=x/y;
假设经过统计后被除数x的定标值为Qx,除数y的定标值为Qy,商z的定标值为Qz,则
z=x/y,
Qxx,2q,Qzz,2=,q,Qyy,2q
QQQ(,,)zxyx,2qz,qyq
所以定点表示的除法为:
intx,y,z;
z=L_shl(x,(Qz-Qx+Qy))/y;//Qz
2.32位以上的除法
这种情况下位数超出了标准c语言的数的表示范围,只能用数组来保存变量。
#defineNN_DIGITunsignedint
NN_DIGITx[2*digits];//Qx
NN_DIGITy[digits];//Qy
NN_DIGITz[digits];//Qz
NN_Lshift(x,x,(Qz-Qx+Qy),2);
NN_Div(z,x,2*digits,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;所以有
intx=18841,y=18841;
7
CIITechnologies,Inc.浮点转定点方法总结
z=L_shl(x,(15-10+9))/18841;//308690944L/18841=16384
15因为商z的定标值为15,所以定点z=16384即为浮点z=16384/2=0.5。
1.2.4三角函数运算
1正弦和余弦
一般求cos、sin用查表法,方法是预先定义正弦和余弦表,表的长度及表中各元素的定标是根据精度要求确定的,精度要求越高,表的长度及元素的定标都可以增加。
余弦表制作步骤:
1)计算cos(2*pi*t/N),其中0<=t<=N-1,N是0,2*pi之间的采样点数。
2)将以上结果(浮点数)按精度要求定标,如Q15,
3)建立数组tab_cos[N],将以上结果作为该数组的元素。
正弦表的定义方法同上。
附录2中给出了余弦表tab_cos[360]和正弦表tab_sin[360],精度是Q15。
例1求cos(2*pi*x/32),x是定标为Qx的整数
cos(2*pi*x/32)=cos((2*pi*(360*x/32)/360);
程序如下:
intu=(L_mult(360,x)/32)%360;//Qx
intresult;
result=tab_cos[u];//Qx
例2求cos(x),x是定标为Qx的整数
cos(x)=cos(2*pi*(360*x/(2*pi))/360),
程序如下:
intpi_Qx=3.1415*(1<intu=(L_mult(360,x)/(2*pi_Qx))%360;//Q0
intresult;
result=tab_cos[u];//Qx
上式中将pi定标为Qx的定点数。
如何进一步提高精度
一般可以增加表的长度即采样点数来提高精度,但在现有采样情况下,也有办法来提高精度。
方法是求出两采样点之间的斜率,根据当前采样点的位置求出更加精确的值。
position
tab_cos[t]
tab_cos[t+1]
tt+1
例3求cos(x),x是定标为Qx的整数
intpi_Qx=3.1415*(1<8
CIITechnologies,Inc.浮点转定点方法总结
intu=(L_mult(360,x)/(2*pi_Qx))%360;//Q0
intpos=(L_mult(360,x))%(2*pi_Qx);
intresult;
result=tab_cos[u]+(tab_cos[(u+1)%360]–tab_cos[u])*pos/(2*pi_Qx);
上面(u+1)%360以防u=359时越界。
2反正切atan()
反正切函数
y=atan(x)
在x=-0.5,0.5之间近似线性,可以用y=x代替,在abs(x)>0.5时可以采用拟合的方法。
因此:
xabs(x)<0.5
y=atan(x)?
(-0.06)*x.^2+0.5*x+0.30.5拟合可以调用matlab的命令ployfit来做,例如:
x=[start:
0.1:
stop];
y=atan(x);
pa=polyfit(x,y,2);
上式中的运算都是简单的乘法运算,较为简单。
1.2.5开方运算
浮点开方运算描述为:
floatx,y;
y=sqrt(x);
定点求开方有多种方法,各种方法在收敛速度上不尽相同,下面介绍几种常用的迭代算法。
1(Newton-Raphson-Babylonian算法:
给定整数N,求sqrt(N)。
首先确定初值x[0],然后利用一个简单的迭代公式:
x[n+1]=(x[n]+N/x[n])/2
迭代次数的选择:
迭代次数与初值x[0]的选取很有关系,x[0]越接近sqrt(N),收敛越快。
但总的来说,该方法收敛较快。
缺点是收敛时间不确定。
2(确定收敛速度的算法:
该方法描述如下:
intsqrt(intx)
{inttest,step;
if(x<0)return(-1);if(x==0)return(0);
step=1<<15;
test=0;
while(step!
=0)
{
registerinth;
9
CIITechnologies,Inc.浮点转定点方法总结
h=(test+step)*(test+step);
if(h<=x){test+=step;}
if(h==x)break;
step>>=1;
}
return(test);}
以上例子是32位开放运算,32位以上的开方运算可参考附录1voidfixsqrt(UINT4*a,
UINT4*b,intdigits),方法同上。
求开方还可以运用线性拟合的方法,由于曲线变化较快,必须根据自变量的范围分段拟合才
能达到理想的精度。
1.3附录
1.3.1附录1:
定点函数库
/*___________________________________________________________________________
||
|FunctionName:
L_add|
||
|Purpose:
|
||
|32bitsadditionofthetwo32bitsvariables(L_var1+L_var2)with|
|overflowcontrolandsaturation;theresultissetat+2147483647when|
|overflowoccursorat-2147483648whenunderflowoccurs.|
||
|Complexityweight:
2|
||
|Inputs:
|
||
|L_var132bitlongsignedinteger(Word32)whosevaluefallsinthe|
|range:
0x80000000<=L_var3<=0x7fffffff.|
||
|L_var232bitlongsignedinteger(Word32)whosevaluefallsinthe|
|range:
0x80000000<=L_var3<=0x7fffffff.|
||
|Outputs:
|
||
|none|
||
|ReturnValue:
|
||
|L_var_out|
10
CIITechnologies,Inc.浮点转定点方法总结
|32bitlongsignedinteger(Word32)whosevaluefallsinthe|
|range:
0x80000000<=L_var_out<=0x7fffffff.|
|___________________________________________________________________________|*/
Word32L_add(Word32L_var1,Word32L_var2)
/*_____________________________________________