![Go语言底层原理剖析](https://wfqqreader-1252317822.image.myqcloud.com/cover/131/40795131/b_40795131.jpg)
2.3 IEEE-754浮点数标准
IEEE-754规范使用以2为底数的指数表示小数,这和使用以10为底数的指数表示法(即科学计数法)非常类似。表2-1给出了几个例子,如0.085可以用指数的形式表示为1.36×2^-4,其中1.36为系数,2为底数,-4为指数。
表2-1 数字的表示方法示例
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_45_2.jpg?sign=1739254304-tXmCIZnK3AniuMYCMQ65q9w6DeJOLO24-0-a95f1eb34f00288638ccdd3bca864af4)
IEEE-754的浮点数存在多种精度。很显然,更多的存储位数可以表达更大的数或更高的精度。在高级语言中一般存在两种精度的浮点数,即大部分硬件浮点数单元支持的32位的单精度浮点数与64位的双精度浮点数。如表2-2所示,两种精度的浮点数具有不同的格式。
表2-2 单精度与双精度浮点数格式
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_46_1.jpg?sign=1739254304-yPKILYsVmtNVGlMw3roa1JJVG7TyofQg-0-b6d0d07967fdf30ac3e8ef30cb63be51)
其中,最开头的1位为符号位,1代表负数,0代表正数。符号位之后为指数位,单精度为8位,双精度为11位。指数位存储了指数加上偏移量的值,偏移量是为了表达负数而设计的。例如当指数为-4时,实际存储的值为-4+127=123。剩下的是小数位,小数位存储系数中小数位的准确值或最接近的值,是0到1之间的数。小数位占用的位数最多,直接决定了精度的大小。以数字0.085为例,单精度下的浮点数表示如表2-3所示。
表2-3 数字0.085的单精度浮点数表示
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_46_2.jpg?sign=1739254304-Amyw7tkPhg9DYANMAQuWauBwSGjve1q2-0-dc995e00c20607ec78237f1a79cb7269)
2.3.1 小数部分计算
小数部分的计算是最复杂的,其存储的可能是系数的近似值而不是准确值。小数位的每一位代表的都是2的幂,并且指数依次减少1。以0.085的浮点表示法中系数的小数部分(0.36)为例,对应的二进制数为010 1110 0001 0100 0111 1011,其计算步骤如表2-4所示,存储的数值接近0.36。
表2-4 小数部分计算步骤
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_46_3.jpg?sign=1739254304-searYCSlIHmFqzfKZZzk12HjKfmJ58rz-0-bdc2c7835c1ea256d5349e08e13e39e5)
续表
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_47_1.jpg?sign=1739254304-17sJ8xXAD4Z00KFRbBdZ4vBkXLF92LOe-0-52d1c7014096abaf9e2165650ed5fbf2)
那么小数位又是如何计算出来的呢?以数字0.085为例,可以使用“乘2取整法”将该十进制小数转化为二进制小数,即
0.085(十进制)
=0.00010101110000101000111101011100001010001111010111000011(二进制)
=1.0101110000101000111101011100001010001111010111000011×2-4
由于小数位只有23位,因此四舍五入后为010 1110 0001 0100 0111 1011,这就是最终浮点数的小数部分。
2.3.2 显示浮点数格式
Go语言标准库的math包提供了许多有用的计算函数,其中,Float32可以以字符串的形式打印出单精度浮点数的二进制值。下例中的Go代码可以输出0.085的浮点数表示中的符号位、指数位与小数位。
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_47_2.jpg?sign=1739254304-GaC2WtMArTfrHLrMSDrR7dAIXyyIJWCo-0-6577886e8109149387f87b6615bd2468)
输出结果为:
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_47_3.jpg?sign=1739254304-FnvnelpyCa1ZzOuN4yPZpy08Cao4VFXw-0-1045a5fd8732650d93560f8263fa9959)
为了验证之前理论的正确性,可以根据二进制值反向推导出其所表示的原始十进制值0.085。思路是将符号位、指数位、小数位分别提取出来,将小数部分中每个为1的bit位都转化为对应的十进制小数,并求和。
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_48_1.jpg?sign=1739254304-1reJS7tTLpPtadVBemrVOjNliiTMGGH2-0-3c544dd6b9a5fa4395b7548d3718b322)
符号位、指数位、小数位,以及最终结果输出如下,验证了之前的理论。
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_48_2.jpg?sign=1739254304-1OF5fKqmvcBdpOIMVp8NzYWC9pvoykVi-0-27a5a79faf68037e2759b6dec174b480)