小护士读书笔记系列之《深入理解计算机系统》第二章信息的表示和处理(四)

小护士读书笔记系列之《深入理解计算机系统》第二章信息的表示和处理(四)

欢迎来到小护士读书笔记系列之《深入理解计算机系统》第二章信息的表示和处理(四),浮点数。该小节作为第二章最后一部分,其内容理解难度远超小护士想象;其实也可以理解,因为浮点数的表示和处理都不得不说IEEE 754,而在有限的篇幅中清晰完整简洁地介绍这个工业标准实在太难。

因此,小护士在这里只要求自己学会理解浮点数怎么存储在二进制中,以及为什么浮点数小数精度有限制。对于其他诸如浮点数运算以及C语言的浮点数表示,本书作者也没有用太长的篇幅去详细介绍,估计他也不想广大读者走火入魔,除非读者是准备搞CPU芯片的;还记得整数表示的小端法吗?

2.4.1 二进制小数(学前班)

从十进制开始重新认识小数点:

12.3410=1×101+2×100+3×101+4×102 12.34 10 = 1 × 10 1 + 2 × 10 0 + 3 × 10 − 1 + 4 × 10 − 2

从二进制开始慢慢了解小数点:

101.112=1×22+0×21+1×20+1×21+1×22 101.11 2 = 1 × 2 2 + 0 × 2 1 + 1 × 2 0 + 1 × 2 − 1 + 1 × 2 − 2

看懂上面两条小等式以后,就总结一下浮点数的小数位怎么在二进制表示:

1.112=1×20+1×21+1×22=1+12+14=1.7510 1.11 2 = 1 × 2 0 + 1 × 2 − 1 + 1 × 2 − 2 = 1 + 1 2 + 1 4 = 1.75 10

看完上面这条小等式,大家应该明白,二进制浮点数不能表示任何小数,只能近似表示,因此就会出现精度问题,而程序员或计算机科学家往往只能选择舍入处理。

2.4.2 IEEE 浮点表示(毕业班)

IEEE 754 选择一个标准的数学等式来规范浮点数的表示:

V=(1)s×2E×M V = ( − 1 ) s × 2 E × M

其中,(可以先扫一眼)

  • V V ,value,归约后的小数值;
  • s s , sign (符号位);
  • 2E×M 2 E × M ,未归约的小数值;
  • 2E 2 E ,阶码的权重;
  • E E ,exponent(指数),偏置之后的阶码值;
  • E=eBias E = e − B i a s ,规格化的情况;
  • E=1Bias E = 1 − B i a s ,非规格化的情况;
  • e e ,exponent(指数),无符号数,阶码;
  • Bias B i a s ,bias(偏差),偏置值;
  • Bias=2k11 B i a s = 2 k − 1 − 1 ,偏置值计算;
  • k k ,阶码位数
  • M M , Mantissa(尾数),尾数的值;
  • M=1+f M = 1 + f ,规格化的情况;
  • M=f M = f ,非规格化的情况;
  • f f ,fraction(尾数的分数表示);

下面以5位比特表示浮点数IEEE为例,持续讲解:

IEEE规定,位分三组:

0 00 00

其中,

  • 第一组是符号
  • 第二组是阶码
  • 第三组是尾数

再来,

  • 第一位作为第一组表示正负数,与补码表示一致,1为负数,0为非负数。
  • 第二位和第三位作为第二组表示 e e ,一个无符号数的阶码,该数可以转为 E E
  • 第四位和第五位作为第三组表示 f f ,分数,该数可以转为 M M

在继续深入前,先了解一下,浮点数表示的三种情况:

  • 规格化的值,第二组的值不为 0 0 也不为 255 255 ,即不全为 0 0 ,也不全为 1 1
  • 非规格化的值,第二组的值全为 0 0
  • 特殊值:正负无穷,第二组的值全为 1 1 ,第三组的值全为 0 0
  • 特殊值:NaN,第二组的值全为 1 1 ,第三组的值不全为 0 0

三种情况:规格化、非规格化、特殊值,它们会有各自的公式代入计算浮点数;

下面会列出表格,说明浮点数的三种情况如何表示:

由于阶码有两位表示,即 k=2 k = 2 ,可得 Bias=2k11=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(尾数的分数表示)

2.4.4~2.4.6 舍入、浮点运算、C语言的浮点数

小护士想说的是,能够坚持看到这里,说明你已经是一个骨骼精奇的可造之材,将来必定能拿下武林至尊的称号。:)

舍入怎么做?这个可以直接参考Java语言的BigDecimal的舍入(rounding)策略。具体来说,无非是向上舍入、向下舍入、四舍五入、向零舍入、向偶数舍入。没听过的舍入策略可以先不管了,基本用不着,除非你要设计发射火箭的小程序。

浮点运算怎么做?书中没有详细介绍,只是说说交换律有很多坑,舍入有很多坑,这些坑可以让火箭发射没多久直接爆炸。真人真事,1996年6月4日,Ariane 5火箭初次航行,没多久偏离飞行路径,解体,爆炸。原因是一个64位浮点数转换成16位有符号整数时,产生了溢出。一个火箭,价值5个亿美元,约33.87个亿人民币,也就是34个小目标。:)

C语言没有强制要求浮点数遵循IEEE标准去做。:)

第二章终于搞完啦

接下来,要开始第三章啦,准备手撸汇编和C语言,准备好了吗?

请期待下一篇小护士读书笔记系列之《深入理解计算机系统》第三章程序的机器级表示(一)。

你可能感兴趣的:(深入理解计算机系统,读书笔记)