理论
浮点数在计算机中存储也是以二进制的形式,遵循 IEEE 二进制算数标准:

IEEE 标准从逻辑上采用一个三元组{S,E,M}来表示一个数 V:
-
符号:s 用 0 和 1 分别表示正和负。
-
尾数:M 用原码表示,根据浮点数的规格化方法,尾数域的最高有效位总是 1,由此,该标准约定这一位不予存储,而是认为隐藏在小数点的左边,因此,尾数域所表示的值是 1.M(实际存储的是M),这样可使尾数的表示范围比实际存储多一位。
-
阶数:E 用移码表示,指数的大小有正负,为避开阶码的符号,阶码通常采用移码方式来表示,将数据的指数 e 加上一个固定的偏移常数后,作为该数的阶码,这样做既可避免出现正负指数,又可保持数据的原有大小顺序,便于进行比较操作。

上面这个图简单说就是:
- float : 符号(1位)、阶码(8位)、尾数(23位)
- double:符号(1位)、阶码(11位)、尾数(52位)
示例
例1:将十进制 float 类型 9.0 转换为二进制表示
- 将 9.0 转换为二进制表示:
;
- 使用科学计数法表示:
;
- 确定符号(1位),由于是正数,所以符号位是:
;
- 确定阶码(8位),指数是 3,但是这里需要用移码方式来表示。8 位的指数范围是:-127~128,所以需要偏移 127 才能保证没有负数,就是 130,用二进制表示:
;
- 确定尾数(23位):尾数为:
,后面需要补 0 直到 23 位:
;
- 最终 float 类型 9.0 的二进制表示为:
。
例2:将二进制 float 类型 11000000101000000000000000000000 转换为十进制表示
- 截取符号(1位),由于是
,所以为负数;
- 截取阶码(8位),
,转换为十进制是 129,这是移码的表示方式,需要反向偏移 127,所以指数为:2;
- 截取尾数(23位),忽略后面的 0,尾数为:
;
- 由此可以推断出,科学计数法表示:
;
- 不使用科学计数法,二进制表示:
;
- 最终十进制表示为:
。
总结
上面都是简单的示例,用来了解转换步骤,至于 double 类型也是大同小异。
对于带有小数部分的浮点数,例如:8.25 如何转化;以及阶数的非规格化处理等等,这些不过多展开,建议大家自己看下《深入理解计算机系统》这本书。
最后附上一个【IEEE单精度浮点数转换工具】方便大家测试。
网友评论