浮点转定点方法总结.docx

上传人:b****8 文档编号:29700829 上传时间:2023-07-26 格式:DOCX 页数:26 大小:50.15KB
下载 相关 举报
浮点转定点方法总结.docx_第1页
第1页 / 共26页
浮点转定点方法总结.docx_第2页
第2页 / 共26页
浮点转定点方法总结.docx_第3页
第3页 / 共26页
浮点转定点方法总结.docx_第4页
第4页 / 共26页
浮点转定点方法总结.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

浮点转定点方法总结.docx

《浮点转定点方法总结.docx》由会员分享,可在线阅读,更多相关《浮点转定点方法总结.docx(26页珍藏版)》请在冰豆网上搜索。

浮点转定点方法总结.docx

浮点转定点方法总结

浮点转定点方法总结

—孔德琦

 

定点运算方法

1.1数的定标

对某些处理器而言,参与数值运算的数就是16位的整型数。

但在许多情况下,数学运算过程中的数不一定都是整数。

那么,如何处理小数的呢?

应该说,处理器本身无能为力。

那么是不是就不能处理各种小数呢?

当然不是。

这其中的关键就是由程序员来确定一个数的小数点处于16位中的哪一位。

这就是数的定标。

通过设定小数点在16位数中的不同位置,就可以表示不同大小和不同精度的小数了。

数的定标用Q表示法。

表1.1列出了一个16位数的16种Q表示能表示的十进制数值范围和近似的精度。

Q表示

精度(近似)

十进制数表示范围

Q15

-1≤X≤

Q14

-2≤X≤

Q13

-4≤X≤

Q12

-8≤X≤

Q11

-16≤X≤

Q10

-32≤X≤

Q9

-64≤X≤

Q8

-128≤X≤

Q7

-256≤X≤

Q6

-512≤X≤

Q5

-1024≤X≤

Q4

-2048≤X≤

Q3

-4096≤X≤

Q2

-8192≤X≤

Q1

-16384≤X≤

Q0

1

-32768≤X≤32767

表1.1Q表示、S表示及数值范围

从表1.1可以看出,同样一个16位数,假设小数点设定的位置不同,它所表示的数也就不同。

例如:

16进制数2000H=8192,用Q0表示

16进制数2000H=,用Q15表示

从表1.1还可以看出,不同的Q所表示的数不仅范围不同,而且精度也不相同。

Q越大,数值范围越小,但精度越高;相反,Q越小,数值范围越大,但精度就越低。

例如,Q0的数值范围是-32768到+32767,其精度为1,而Q15的数值范围为-1到,精度为。

因此,对定点数而言,数值范围与精度是一对矛盾,一个变量要想能够表示比拟大的数值范围,必须以牺牲精度为代价;而想提高精度,那么数的表示范围就相应地减小。

在实际的定点算法中,为了到达最正确的性能,必须充分考虑到这一点。

浮点数与定点数的转换关系可表示为:

浮点数(x)转换为定点数(

):

定点数(

)转换为浮点数(x):

例如,浮点数,定标Q=15,那么定点数

,式中

表示下取整。

反之,一个用Q=15表示的定点数16384,其浮点数为16384×2-15

=。

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⇒

=

=

一般情况,我们取x,y和z的定标值相同,即Qx=Qy=Qz=Qa。

所以定点加法可以描述为:

shortx,y,z;//Qa

z=add(x,y);//Qa

函数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

定点减法:

NN_DIGITx[digits],y[digits],z[digits];//Qa

NN_Sub(z,x,y,digits);Qa

应注意的是以上32位定点加减法都是无符号数操作。

1.16位乘法

设浮点乘法运算的表达式为:

floatx,y,z;

z=xy;

假设经过统计后x的定标值为Qx,y的定标值为Qy,乘积z的定标值为Qz,那么

z=xy⇒

=

=

所以定点表示的乘法为:

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

设,,那么浮点运算值为z×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即为浮点的。

例2

设,,那么浮点运算值为z×36.8=677.12;

#defineNN_DIGITunsignedint

设Qx=20,Qy=20,Qy=20,所以

NN_DIGITx=18.4*(1<<20);//Q20

NN_DIGITy=*(1<<20);//Q20

NN_DIGITz[2];//Q20

NN_Mult(z,&x,&y,1);//Q40

NN_Rshift(z,z,20,1);//Q(40-20)

1.32位除法

设浮点除法运算的表达式为:

floatx,y,z;

z=x/y;

假设经过统计后被除数x的定标值为Qx,除数y的定标值为Qy,商z的定标值为Qz,那么

z=x/y⇒

=

所以定点表示的除法为:

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:

设,,浮点运算值为z=x/y=18.4/36.8=0.5;

根据上节,得Qx=10,Qy=9,Qz=15;所以有

intx=18841,y=18841;

z=L_shl(x,(15-10+9))/18841;//308690944L/18841=16384

因为商z的定标值为15,所以定点z=16384即为浮点z=16384/215。

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的定点数。

如何进一步提高精度

一般可以增加表的长度即采样点数来提高精度,但在现有采样情况下,也有方法来提高精度。

方法是求出两采样点之间的斜率,根据当前采样点的位置求出更加精确的值。

例3求cos(x),x是定标为Qx的整数

intpi_Qx=3.1415*(1<

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时可以采用拟合的方法。

因此:

y=atan(x)≈

(-0.06)*x.^20.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;

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|

|32bitlongsignedinteger(Word32)whosevaluefallsinthe|

|range:

0x80000000<=L_var_out<=0x7fffffff.|

|___________________________________________________________________________|

*/

Word32L_add(Word32L_var1,Word32L_var2)

/*___________________________________________________________________________

||

|FunctionName:

L_sub|

||

|Purpose:

|

||

|32bitssubtractionofthetwo32bitsvariables(L_var1-L_var2)with|

|overflowcontrolandsaturation;theresultissetat+214783647when|

|overflowoccursorat-214783648whenunderflowoccurs.|

||

|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|

|32bitlongsignedinteger(Word32)whosevaluefallsinthe|

|range:

0x80000000<=L_var_out<=0x7fffffff.|

|___________________________________________________________________________|

*/

Word32L_sub(Word32L_var1,Word32L_var2)

/*___________________________________________________________________________

||

|FunctionName:

add|

||

|Purpose:

|

||

|Performstheaddition(var1+var2)withoverflowcontrolandsaturation;|

|the16bitresultissetat+32767whenoverflowoccursorat-32768|

|whenunderflowoccurs.|

||

|Complexityweight:

1|

||

|Inputs:

|

||

|var1|

|16bitshortsignedinteger(Word16)whosevaluefallsinthe|

|range:

0xffff8000<=var1<=0x00007fff.|

||

|var2|

|16bitshortsignedinteger(Word16)whosevaluefallsinthe|

|range:

0xffff8000<=var1<=0x00007fff.|

||

|Outputs:

|

||

|none|

||

|ReturnValue:

|

||

|var_out|

|16bitshortsignedinteger(Word16)whosevaluefallsinthe|

|range:

0xffff8000<=var_out<=0x00007fff.|

|___________________________________________________________________________|

*/

Word16add(Word16var1,Word16var2)

/*___________________________________________________________________________

||

|FunctionName:

sature|

||

|Purpose:

|

||

|Limitthe32bitinputtotherangeofa16bitword.|

||

|Inputs:

|

||

|L_var1|

|32bitlongsignedinteger(Word32)whosevaluefallsinthe|

|range:

0x80000000<=L_var1<=0x7fffffff.|

||

|Outputs:

|

||

|none|

||

|ReturnValue:

|

||

|var_out|

|16bitshortsignedinteger(Word16)whosevaluefallsinthe|

|range:

0xffff8000<=var_out<=0x00007fff.|

|___________________________________________________________________________|

*/

Word16sature(Word32L_var1)

/*_____________________________________

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 商业计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1