浮点数的表示与运算

声明:本篇博文中的图片均来源于CMU 15-213的PPT

一、IEEE浮点数标准(IEEE Floating Point Standard)

type(bits)

sign bit(s)

exponent(E)

fractional value(M)

single(32)

1

8

23

double(64)

1

11

52

Extended Presicion(80)(Intel only)

1

15

63/64

浮点数的表示与运算

对于f取值的五种分类

  M / frac value E 什么情况下会产生
Normalized Value M = 1.xxxxx , 其中xxxxx被frac value表示 000...01 <= E <= 111...10 正常情况下多为这种数

Denormed Value

M = 0.xxxxx, 其中xxxxx被frac value表示 E = 111...11 当数非常接近0时
+0 / -0 frac value = 000...00 E = 000...00 当数非常非常接近0,以至于Denormed Value也表示不了的时候

 +∞ / -∞

frac value = 000...00

E = 111...11

除以0,或者溢出时
nan (not a number) frac value ≠ 0 E = 111...11 0/0,或者0*∞时

 如果把浮点数看做带符号的整数,那么它们的大小关系可以用下图表示出来:(float->int, double->long long)

浮点数的表示与运算

事实上,这正体现了这种浮点数表示法的优点,它可以像整型一样轻易地比较大小

为了更加深入地理解浮点数的取值分布,可以考虑一个低位浮点数,这里取8位浮点数,其中exp(指数)占4位,frac(数值)占3位,我们得到下表

浮点数的表示与运算

就着这张表理一下浮点数表示的一些细节

  1. 对于normalized value,相当于就是二进制版的“科学计数法”。因此我们就知道了为什么M的首位要自动补1了,因为如果首位是0,说明E的值有问题,该调整E使得M的首位变成1,这样的话,无论如何M的首位都会是1。既然如此,又何必浪费1bit去表示1呢?况且,原本23位的M现在能表示24位的数了,看到8的倍数就觉得好。
  2. 无符号的4位的E可以表示2^4-1=15种可能,除去1111和0000还有13中,由于E可正可负,因此我们选取一个偏置,在读到E时自动减去偏置。这里偏置的选择是2^3-1=7,E原本的取值是0001~1110,即1~14,减去偏置后为-6~7。和带符号整型的表示略有区别,带符号整型的“偏置”不会-1,所以这里的E正值范围大于负值,带符号整型的负值范围大于正值
  3. normalized value没能物尽其用,因此引入denormed value。denormed value和最小的normalized value之间的过渡平滑
  4. 对于normalized value之间的间距与normalized value和denormed value之间的间距,如下图所示浮点数的表示与运算

            浮点数的表示与运算

二、浮点数运算

基本理念:先做无穷精度的计算,再近似舍入

1. 舍入

舍入分四种,分别是向0舍入,向上(+∞)舍入,向下(-∞)舍入,以及向偶数舍入

浮点数的舍入采取最后一种,具体来说,类比“四舍五入”,如果不是.50000就正常舍入,如果是就像最近的偶数舍入,并不是说舍入结果一定是偶数

举例:

浮点数的表示与运算

2. 乘法

浮点数的表示与运算

3. 加法

浮点数的表示与运算

4. Mathematical Properties of Addition

  • 交换律√
  • 结合律x浮点数的表示与运算
  • 0是加法单位元√

5. Mathematical Properties of Multiplication

  • 交换律√
  • 结合律x浮点数的表示与运算
  • 1是乘法单位元√
  • 分配率x
    • 例如
    • cout << 1e200*1e200-1e200*1e200 << endl; // nan
    • cout << 1e200*(1e200-1e200<< endl; // 0

三、浮点数与整数的相互转化(Casting)

  • float -> int 截取整数部分,不进行舍入
  • int->double(32位->52位)没有问题
  • int->float (32位->23位)需要舍入,思路还是先弄成无限精度,再舍入