浮点数表示

来源:互联网 发布:数控火焰切割手动编程 编辑:程序博客网 时间:2024/05/18 02:17

在充满0,1的计算机存储空间中怎么表示高精度浮点数?


1 浮点数二进制表示方式

C语言和C#语言中,对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit,double数据占用64bit,我们在声明一个变量float f= 2.25f的时候,是如何分配内存的呢?如果胡乱分配,那世界岂不是乱套了么,其实不论是float还是double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24,而double 遵从的是R64.53。
无论是单精度还是双精度在存储中都分为三个部分:
 1. 符号位(Sign):0代表正,1代表为负;
 2. 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储;
 3. 尾数部分(Mantissa):尾数部分;
其中float的存储方式如下图所示:
这里写图片描述
而双精度的存储方式为:
这里写图片描述
R32.24和R64.53的存储方式都是用科学计数法来存储数据的,比如8.25用十进制的科学计数法表示就为:8.25* 。而120.5可以表示为:1.205* ,这些小学的知识就不用多说了吧。而我们傻蛋计算机根本不认识十进制的数据,他只认识0,1,所以在计算机存储中,首先要将上面的数更改为二进制的科学计数法表示,8.25用二进制表示可表示为1000.01,我靠,不会连这都不会转换吧?那我估计要没辙了。120.5用二进制表示为:1110110.1用二进制的科学计数法表示1000.01可以表示为1.0001* 。任何一个数都的科学计数法表示都为1.xxx* ,尾数部分就可以表示为xxxx,第一位都是1嘛,干嘛还要表示呀?可以将小数点前面的1省略,所以23bit的尾数部分,可以表示的精度却变成了24bit,道理就是在这里,那24bit能精确到小数点后几位呢,我们知道9的二进制表示为1001,所以4bit能精确十进制中的1位小数点,24bit就能使float能精确到小数点后6位,而对于指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127-128了,所以指数部分的存储采用移位存储,存储的数据为元数据+127,单精度浮点数120.5的存储方式如下图所示:
这里写图片描述
总结:float与double类型都是将十进制数转换为二进制数再小数部分与指数部分分开存储,两者均使用自己独立的符号位,且由于二进制只为1或0,而一个二进制数必然可以设置成为1.XXX,其中X为0或1,所以该数可以默认为1.XXX,其中XXX部分即为所存储的小数部分。


2 浮点VS定点

首先就说价格,浮点处理器按照MIPS/unit money价格来说大多要贵于定点处理器,因为浮点处理器工艺复杂且集成规模大,浮点处理单元都是要贵于定点处理单元。
定点处理器很早就被发明出来了,这个就直接导致早期的算法工程师使用定点处理器,加上定点处理器价格便宜很多工程师没有转而使用新型的浮点处理器,浮点处理器在90年代初期被发明。
为什么很多大公司同时也是老公司使用的是定点处理器,不是全部因为他们觉得定点好,而是积累,他们的算法工程师做了几十年定点算法工作,如果转而去搞浮点运算势必造成落后于对手,而且高级定点算法也不会弱,所以他们更愿意开发更好的定点算法而不去做浮点运算,同时定点处理器极其低廉的价格也是吸引那些公司的一个重要原因。
对于精度损失,其实定点远远大于浮点,这个是无庸置疑的。音频算法精度损失只会造成声有缺陷但是几乎不影響听觉;但是对于导弹轨道或者雷达等计算存在精度损失,那个影响是巨大,众所周知军用DSP绝大多数都是浮点处理器,精度高、速度快,缺點就是功耗大、价格昂贵,但是我想对于追求性能的我们来说,后面的两个缺点不算缺点,呵呵。
对于使用定点处理器,不代表算法也是定点运算的,因为现在定点处理器非常便宜,很多公司使用廉价的定点处理器来模拟运算浮点运算(因为定点处理器太便宜的,我来比喻一下,一个速度为100的定点处理器为10块钱,而一个速度为10的浮点处理器价格为100,这样很多拥有好的算法转换的公司更愿意使用定点来模拟浮点。实际处理器都是按照MIPS来做单位,我前面只是一个比喻),
下面我在说一个问题,因为浮点运算效率高,每个浮点运算的单元处理运算速度非常快,所以浮点运算处理器可以带来低的延迟,而定点处理器尤其那些还要部分模拟浮点运算的东西延迟吓人。
最后我要说的,对于一个好的算法工程师使用定点和浮点都能作出很好的东西,但是对于两个级别相同的算法工程师,使用浮点处理器作出来的东西理论上是好于定点处理器的,定点处理器这个时候除了便宜和功耗低找不出其他闪亮点。


3 浮点运算实现方式

一般的定点处理器的寄存器字长都是有限的,一般为16位或者32位,还有24位的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。因此,对定点数而言,数值范围与精度是一对矛盾,一个变量要想能够表示比较大的数值范围,必须以牺牲精度为代价;而想精度提高,则数的表示范围就相应地减小。在实际的定点算法中,为了达到最佳的性能,必须充分考虑到这一点,即权衡动态范围和精度。
浮点数与定点数的转换关系可表示为:
 1. 浮点数(x)转换为定点数(xq):xq=(int)x* 2Q,当然浮点转换为顶点时需要考虑以上提到的舍入方式,不同的舍入方式,其精度也不同;
 2. 定点数(xq)转换为浮点数(x):x=(float)xq*2-Q;
定点模拟的浮点操作:浮点的加减法需要先把小数点统一到一个相同的位置,然后再加减,统一小数点位置可以用左移到一个Q值高的定点位置或者右移到Q值低的定点位置,显然左移的实现需要保证加减的结果不会导致溢出,而右移的方法需要考虑数据精度是否满足需求。一般的处理器都不会考虑加减运算导致的数值溢出问题,因而程序员需要用更长的字长来防止溢出,或者采用饱和的方式以防止数据的上溢或者下溢,有些芯片会有专门的饱和加减的操作,有些还会包含更长字长的累加器来存储加减的结果以防止溢出。
在很多定点器件中,会提供定点实现浮点运算的库函数供调用。

0 0
原创粉丝点击