计算机体系结构中浮点和定点数据的表示
1、定点数:
定点数指小数点在数中的位置是固定不变的,通常有定点整数和定点小数或者说是定点分数。在对小数点位置作出选择之后即定标定了Q值后,运算中的所有数均应统一为定点整数或定点小数,在运算中不再考虑小数点的位置问题。
(1)定义:数据中小数点位置固定不变的数
(2)种类:定点整数、定点小数(分数fraction)
(3)小数点在符号位与有效位之间,
需要注意的是 定点数受字长的限制,超出范围会有溢出。
2、浮点数:
浮点数中小数点的位置是不固定的,用指数和尾数来表示。通常尾数为纯小数,指数为整数,尾数和指数均为带符号数。尾数的符号表示数的正负;指数的符号则表明小数点的实际位置。
(1)形式:V=MX2E
(2)M:尾数Mantissa
(3)E:指数Exponent
(4)在计算机中M和E表示形式为尾数符号、指数、尾数
需要注意的是,浮点数的精度由尾数决定,数的表示范围由指数决定。
IEEE754的浮点表示
a) 两种基本浮点格式:单精度和双精度。
IEEE单精度格式具有24位有效数字(1个符号位,23位尾数),8位的指数部分,总共占用32 位。IEEE双精度格式具有53位有效数字精度(1个符号位,52位尾数),11位的指数部分,并总共占用64位。
说明:基本浮点格式是固定格式,相对应的十进制有效数字分别为7位和17位。基本浮点格式对应的C/C++类型为float和double。
b) 浮点到定点的四种舍入(截断)方向:
向最接近的可表示的值;当有两个最接近的可表示的值时首选"偶数"值;向负无穷大(向下);向正无穷大(向上)以及向0(截断)。
说明:舍入模式也是比较容易引起误解的地方之一。IEEE 754标准根本不支持四舍五入模式,它的默认模式是最近舍入(Round to Nearest),它与四舍五入只有一点不同,对.5的舍入上,采用取偶数的方式。如:
最近舍入模式:Round(0.5) = 0; Round(1.5) = 2; Round(2.5) = 2;
四舍五入模式:Round(0.5) = 1; Round(1.5) = 2; Round(2.5) = 3;
向0(截断)舍入:C/C++的类型转换。(int) 1.324 = 1,(int) -1.324 = -1;
向负无穷大(向下)舍入:C/C++函数floor()。例如:floor(1.324) = 1,floor(-1.324) = -2。
向正无穷大(向上)舍入:C/C++函数ceil()。ceil(1.324) = 2。Ceil(-1.324) = -1;
后两种舍入方法据说是为了数值计算中的区间算法,但很少被应用。
3、定点数与浮点数区别
定点表示法运算直观,但数的表示动态范围较小(对于32位定点整数而言,数据范围只能从-2147483648到2147483647),不同的数运算时要考虑比例因子的选取,以防止溢出,对于某些应用场合,如高品质音频,要求高达24bit即144dB的动态范围,使用定点运算就需要不断的调整比例因子以满足精度要求。浮点表示法运算时可以不考虑溢出(即使对于32位单精度浮点而言,其数据范围也能从,但浮点运算在实际的平台实现复杂度较高,即运算复杂度较高,要掌握定、浮点数的转换方法及浮点数规格化方法。
单精度格式浮点数表示范围
指数尾数数值(二进制)数值(十进制)
最大数0xfe0x7fffff1.(23个1)*2^(+127)3,4028236692093846346337460743177e+38
最小数0x10x01.(23个0)*2^(-126)1,1754943508222875079687365372222e-38
最小弱规范数0x00x10.(22个0)1*2^(-126)1,4012984643248170709237295832899e-45
定点数据的定标Q
一般的定点处理器的寄存器字长都是有限的,一般为16位或者32位,还有24位的DSP处理器,当然字长越长,所能表示的数据范围越大,精度也越高。定点DSP芯片的数以2的补码形式表示,以16位字长为例。每个16位数用一个符号位来表示数的正负,0表示数值为正,l则表示数值为负。其余15位表示数值的大小。因此,
二进制数0010000000000000b=0x2000H=8192
二进制数1111111111111100b=0xfffcH=-4
对于定点处理器而言,它并不清楚数据的小数点位置,它只能根据指令把数据做统一的运算处理,此时程序员需要确定小数点的位置即定标,然后定标过程中需要考虑数据的动态范围和精度要求。定点数的定标一般采用Q表示法,Q表示小数点在字宽中的位置。同样一个16位数,若小数点设定的位置不同(即定标不同),它所表示的数也就不同。例如,
16进制数2000H=8192,用Q0表示
16进制数2000H=0.25,用Q15
显然,不同的Q所表示的数不仅范围不同,而且精度也不相同。Q越大,数值范围越小,但精度越高;相反,Q越小,数值范围越大,但精度就越低。例如,Q0 的数值范围是一32768到+32767,其精度为1,而Q15的数值范围为-1到0.9999695,精度为1/32768=0.00003051。因此,对定点数而言,数值范围与精度是一对矛盾,一个变量要想能够表示比较大的数值范围,必须以牺牲精度为代价;而想精度提高,则数的表示范围就相应地减 小。在实际的定点算法中,为了达到最佳的性能,必须充分考虑到这一点,即权衡动态范围和精度。
浮点数与定点数的转换关系可表示为:
浮点数(x)转换为定点数(xq):xq=(int)x* 2Q,当然浮点转换为顶点时需要考虑以上提到的舍入方式,不同的舍入方式,其精度也不同。
定点数(xq)转换为浮点数(x):x=(float)xq*2-Q
定点vwin 的浮点操作
浮点的加减法需要先把小数点统一到一个相同的位置,然后再加减,统一小数点位置可以用左移到一个Q值高的定点位置或者右移到Q值低的定点位置,显然左移的实现需要保证加减的结果不会导致溢出,而右移的方法需要考虑数据精度是否满足需求。一般的DSP处理器都不会考虑加减运算导致的数值溢出问题,因而程序员需要用更长的字长来防止溢出,或者采用饱和的方式以防止数据的上溢或者下溢,有些DSP芯片会有专门的饱和加减的操作,有些DSP还会包含更长字长的累加器来存储加减的结果以防止溢出。
定点乘法运算的模拟,则需要知道乘数和被乘数的Q值以及乘积结果的Q值,
设浮点乘法运算的表达式为:
float x,y,z;
z=xy;
假设经过统计后x的定标值为Qx,y的定标值为Qy,乘积z的定标值为Qz,则
z=xy
zq*2-Qx=xq*yq*2-(Qx+Qy)
zq=(xqyq)2Qz-(Qx+Qy)
所以定点表示的乘法为:
int x,y,z;
long temp;
temp=(long)x;
z=(temp*y)>>(Qx+Qy-Qz);
例 定点乘法。
设x=18.4,y=36.8,则浮点运算值为=18.4*36.8=677.12;
根据上节,得Qx=10,Qy=9,Qz=5,所以
x=18841;y=18841;
temp=18841L;
z=(18841L*18841)>>(10+9-5)=354983281L>>14=21666;
因为z的定标值为5,故定点z=21666,即为浮点的z=21666/32=677.08。
对于定点除法运算而言,和乘法类似,需要清楚数据的Q值,然后对结果做调整。
设浮点除法运算的表达式为:
float x,y,z;
z=x/y;
假设经过统计后被除数x的定标值为Qx,除数y的定标值为Qy,商z的定标值为Qz,则
z=x/y
zq*2-Qz=(xq*2-Qx)/(yq*2-Qy)
zq=(xq*2(Qz-Qx+Qy))/yq
所以定点表示的除法为:
int x,y,z;
long temp;
temp=(long)x;
z=(temp<<(Qz-Qx+Qy))/y;
例1.6定点除法。
设x=18.4,y=36.8,浮点运算值为z=x/y=18.4/36.8=0.5;
根据上节,得Qx=10,Qy=9,Qz=15;所以有
z=18841,y=18841;
temp=(long)18841;
z=(18841L<<(15-10+9)/18841=3O8690944L/18841=16384;
因为商z的定标值为15,所以定点z=16384,即为浮点z=16384/215=0.5。
因而为了适应各种定点运算操作,需要清楚操作数和结果的Q值,实际上Q值对应于变量的动态范围,只要清楚数据的动态范围,也就能确定Q值了。一般可以通过对数据的动态范围进行理论和统计的分析来得出合理的动态范围,而且在进行数据操作时,还需要考虑饱和运算以防止溢出。
如何优化定点的运算精度
定点计算需要注意的就是保证精度,数据动态范围很大的情况下,有限的字长表示不了那么大动态范围的情况下,有以下方法保证尽可能高的运算精度
分级缩放数据,以FFT计算为例,可以分级scale,蝶形运算的理论表明每一级的增益不会大于2,所以每次蝶形运算后做一次右移要比先把输入数据缩放到不会溢出的水平上精度更高。
Normalization的归一化,同样的FFT运算,首先根据输入数据的幅度的最大情况,计算一个不会导致溢出的缩放因子,然后对整个输入做归一化的scale,FFT之后再de-normalization能显著的提高精度,同时又能适应输入数据较大的动态范围。
Pseudo floating-point:即把定点数据表示为指数和尾数的形式,用虚拟浮点数据的方式来满足高动态范围的需求,当然pseudo floating-point的表示还是需要做归一化来求解指数的。