欢迎来到小护士读书笔记系列之《深入理解计算机系统》第二章信息的表示和处理(四),浮点数。该小节作为第二章最后一部分,其内容理解难度远超小护士想象;其实也可以理解,因为浮点数的表示和处理都不得不说IEEE 754,而在有限的篇幅中清晰完整简洁地介绍这个工业标准实在太难。
因此,小护士在这里只要求自己学会理解浮点数怎么存储在二进制中,以及为什么浮点数小数精度有限制。对于其他诸如浮点数运算以及C语言的浮点数表示,本书作者也没有用太长的篇幅去详细介绍,估计他也不想广大读者走火入魔,除非读者是准备搞CPU芯片的;还记得整数表示的小端法吗?
从十进制开始重新认识小数点:
从二进制开始慢慢了解小数点:
看懂上面两条小等式以后,就总结一下浮点数的小数位怎么在二进制表示:
看完上面这条小等式,大家应该明白,二进制浮点数不能表示任何小数,只能近似表示,因此就会出现精度问题,而程序员或计算机科学家往往只能选择舍入处理。
IEEE 754 选择一个标准的数学等式来规范浮点数的表示:
其中,(可以先扫一眼)
下面以5位比特表示浮点数IEEE为例,持续讲解:
IEEE规定,位分三组:
0 00 00
其中,
再来,
在继续深入前,先了解一下,浮点数表示的三种情况:
三种情况:规格化、非规格化、特殊值,它们会有各自的公式代入计算浮点数;
下面会列出表格,说明浮点数的三种情况如何表示:
由于阶码有两位表示,即 k=2 k = 2 ,可得 Bias=2k−1−1=1 B i a s = 2 k − 1 − 1 = 1
位 | 情况 | e e | E E | 2E 2 E | f f | M M | 2E×M 2 E × M | V V | 十进制 |
---|---|---|---|---|---|---|---|---|---|
0 00 00 | 非规格化 | 0 | 0 | 1 | 04 0 4 | 04 0 4 | 04 0 4 | 0 0 | 0.0 0.0 |
0 00 01 | 非规格化 | 0 | 0 | 1 | 14 1 4 | 14 1 4 | 14 1 4 | 14 1 4 | 0.25 0.25 |
0 00 10 | 非规格化 | 0 | 0 | 1 | 24 2 4 | 24 2 4 | 24 2 4 | 12 1 2 | 0.5 0.5 |
0 00 11 | 非规格化 | 0 | 0 | 1 | 34 3 4 | 34 3 4 | 34 3 4 | 34 3 4 | 0.75 0.75 |
0 01 00 | 规格化 | 1 | 0 | 1 | 04 0 4 | 44 4 4 | 44 4 4 | 1 1 | 1.0 1.0 |
0 01 01 | 规格化 | 1 | 0 | 1 | 14 1 4 | 54 5 4 | 54 5 4 | 54 5 4 | 1.25 1.25 |
0 01 10 | 规格化 | 1 | 0 | 1 | 24 2 4 | 64 6 4 | 64 6 4 | 32 3 2 | 1.5 1.5 |
0 01 11 | 规格化 | 1 | 0 | 1 | 34 3 4 | 74 7 4 | 74 7 4 | 74 7 4 | 1.75 1.75 |
0 10 00 | 规格化 | 2 | 1 | 2 | 04 0 4 | 44 4 4 | 84 8 4 | 2 2 | 2.0 2.0 |
0 10 01 | 规格化 | 2 | 1 | 2 | 14 1 4 | 54 5 4 | 104 10 4 | 52 5 2 | 2.5 2.5 |
0 10 10 | 规格化 | 2 | 1 | 2 | 24 2 4 | 64 6 4 | 124 12 4 | 3 3 | 3.0 3.0 |
0 10 11 | 规格化 | 2 | 1 | 2 | 34 3 4 | 74 7 4 | 144 14 4 | 72 7 2 | 3.5 3.5 |
0 11 00 | 特殊值:正无穷 | - | - | - | - | - | - | +∞ + ∞ | - |
1 11 00 | 特殊值:负无穷 | - | - | - | - | - | - | −∞ − ∞ | - |
0 11 01 | NaN | - | - | - | - | - | - | NaN N a N | - |
0 11 10 | NaN | - | - | - | - | - | - | NaN N a N | - |
0 11 11 | NaN | - | - | - | - | - | - | NaN N a N | - |
英特尔于1980年左右,推出类似IEEE754标准,成为后来1985年的工业标准,一直沿用至今;不得不服,老大哥就是老大哥,中兴没芯也是有道理的。要是能去英特尔工作也是一份荣耀,哪怕只是去洗厕所。说偏了,小护士回到正题:
32位浮点数怎么表示?
31 | 30~23 | 22~0 |
---|---|---|
s(符号) | exp(阶码) | frac(尾数的分数表示) |
64位浮点数怎么表示?
63 | 62~52 | 51~32 |
---|---|---|
s(符号) | exp(阶码) | frac(尾数的分数表示) |
31~0 |
---|
frac(尾数的分数表示) |
小护士想说的是,能够坚持看到这里,说明你已经是一个骨骼精奇的可造之材,将来必定能拿下武林至尊的称号。:)
舍入怎么做?这个可以直接参考Java语言的BigDecimal
的舍入(rounding)策略。具体来说,无非是向上舍入、向下舍入、四舍五入、向零舍入、向偶数舍入。没听过的舍入策略可以先不管了,基本用不着,除非你要设计发射火箭的小程序。
浮点运算怎么做?书中没有详细介绍,只是说说交换律有很多坑,舍入有很多坑,这些坑可以让火箭发射没多久直接爆炸。真人真事,1996年6月4日,Ariane 5火箭初次航行,没多久偏离飞行路径,解体,爆炸。原因是一个64位浮点数转换成16位有符号整数时,产生了溢出。一个火箭,价值5个亿美元,约33.87个亿人民币,也就是34个小目标。:)
C语言没有强制要求浮点数遵循IEEE标准去做。:)
接下来,要开始第三章啦,准备手撸汇编和C语言,准备好了吗?
请期待下一篇小护士读书笔记系列之《深入理解计算机系统》第三章程序的机器级表示(一)。