![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=1739948281-EZrlwl4AYohj4IitajYqKUNA8DDzQEQW-0-d4ea9f6e32399d915129e8a89ad9d748)
IEEE-754的浮点数存在多种精度。很显然,更多的存储位数可以表达更大的数或更高的精度。在高级语言中一般存在两种精度的浮点数,即大部分硬件浮点数单元支持的32位的单精度浮点数与64位的双精度浮点数。如表2-2所示,两种精度的浮点数具有不同的格式。
表2-2 单精度与双精度浮点数格式
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_46_1.jpg?sign=1739948281-bNTkPNdKmexq2KQ5eL7flid3GnDahG19-0-b3453dbf2227a122532a62390f0efa2c)
其中,最开头的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=1739948281-4oDShs8p7ju8Ml06xb2GJWDQTTKoMMfL-0-f2c3275c71d05629488dd782e17a1179)
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=1739948281-1oWpQrtTydLCcSEKgEahFJGyF0b3V9iv-0-11d0c3bed58bf21eeda68f7f872e4ef2)
续表
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_47_1.jpg?sign=1739948281-2fvN5M4wngbJlTwo46rHrJfZG1da1OCm-0-941c3ca6c0b4fca70513555ac8c16b0a)
那么小数位又是如何计算出来的呢?以数字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=1739948281-1HlsVUSC1pdbNOIqdrGLt9ZgdnGPPj34-0-327db14546a127e924b9c2e4fdc965bf)
输出结果为:
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_47_3.jpg?sign=1739948281-cUxfMO5DdwMQVs8f0BayUWMpile3CMZt-0-f9c4757fb450b4aa4c87bce89679bfc2)
为了验证之前理论的正确性,可以根据二进制值反向推导出其所表示的原始十进制值0.085。思路是将符号位、指数位、小数位分别提取出来,将小数部分中每个为1的bit位都转化为对应的十进制小数,并求和。
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_48_1.jpg?sign=1739948281-cL7KmQcuxenCKULjOgvyxle4c10dhrKY-0-c3e447f3eec0ba5f1855fa0f81f1ac8d)
符号位、指数位、小数位,以及最终结果输出如下,验证了之前的理论。
![](https://epubservercos.yuewen.com/88BA42/21190707608528606/epubprivate/OEBPS/Images/41662_48_2.jpg?sign=1739948281-LjTyUfCuqBBCC34A3deTlwY7uWFGVfwY-0-f45b1029178bf0cb34e454b52b6dc23e)