在数字信号处理器dsp 中,根据运算方式的不同,可分为浮点运算与定点运算 。顾名思 义,浮点运算在运算过程中,小数点的位置是变动的。定点运算则是不变。浮点运算的优 点是表示数的动态范围大,精度也可以很细。缺点是硬件复杂。定点运算的优点是运算速 度快,硬件相对简单。缺点是运算过程中容易溢出,产生误差。
不管是浮点运算还是定点运算 ,两者都存在有限字长效应。即dsp的处理字长一般是16bit 或者32bit,有限长度的字长总不能精确地表示某些小数。以小数0.1为例,转成二进制就 是0.000110011001100110011001…….。这个数用任何字长的dsp都无法精确表示。这就如 1/3无法用十进制(0.333333……)精确表示一样 。这个时候,dsp会用截取或者舍入的方法 来表示小数。这样做的结果,就会产生量化误差。不过32bit的浮点运算中,这种误差在实 际应用是可以接受的。但将16bit的定点运算运用在高阶iir数字滤波器 中,可能会产生震荡, 因为iir滤波器使用了递归运算,误差在递归过程中会被放大。
ieee745是浮点运算dsp使用最多的小数表示标准。现以0.1 0.2=0.3为例,看下浮点小数在32bit dsp中是如何存储的。
main()
{
float abc=0.1,def=0.2,out_test;
out_test=abc def;
printf("abc=%1.15f,abc在内存中的十六进制值=%x\n",abc,*(int*)(&abc));
printf("def=%1.15f,def在内存中的十六进制值=%x\n",def,*(int*)(&def));
printf("out_test=%1.15f,out_test在内存中的十六进制值=%x\n",out_test,*(int*)(&out_test));
}
打印结果如下:
从上面的打印结果可以看出,0.1在dsp中存储的ieee745格式十六进制值是0x3dcccccd,转换成十进制实际值是0.100000001490116,这个值和0.1的误差已经很小了。这个误差是由舍入引起的。请注意,printf函数中%f默认是打印%1.6f,即只将小数点的后面6位打印出来。所以,如果使用%f来打印结果,显示结果就是abc=0.100000,这样会让人误解dsp存储0.1是精准的。