计算机系统2.4
计算机系统2.4

计算机系统2.4

浮点数

浮点表示对形如V=x\times 2^y的有理数进行编码. 而在个人计算机刚刚诞生的时候, 有许多不同的浮点数规则, 直到IEEE标准的出现, 统一了浮点数的标准.

IEEE 电器和电子工程师协会 该协会也建立了WiFi标准

二进制小数

考虑十进制小数的如下表示:

d_md_{m-1}···d_1d_0.d_{-1}d_{-2}···d_{-n}

这个描述的数值d定义则为:

d=\sum_{i=-n}^{m}10^i\times d_i

而形如:

b_mb_{m-1}···b_1b_0.b_{-1}b_{-2}···b_{-n}

的对b的描述的定义则为:

d=\sum_{i=-n}^{m}2^i\times b_i

很显然, 二进制中小数点作为幂正负的分界线, 小数点左移一位值除2, 右移一位则乘2.

值得注意的是, 在十进制中, 有些有理数不能被有限位数表示, 而有限位二进制小数也只能表示能被写成x\times 2^y的数.

IEEE的浮点表示

刚刚讲的定点表示法不能很有效的表示非常大的数字, 而IEEE浮点标准则使用V=(-1)^S\times M\times 2^E的形式来表示一个数.

  • 符号(Sign) s决定这个数的正负性, 负数s=1, 反之亦然.
  • 尾数(Significand) M是一个二进制小数, 他的范围是1\~2-ε或0\~1-ε.
  • 阶码(Exponent) E的作用是对浮点数加权, 这个权重是2的E次幂.

将浮点数的位表示划分为三个字段, 分别为:

  • 一个单独的符号位s直接编码符号s.
  • k位的阶码字段exp编码阶码E.
  • n位的小数字段frac编码尾数M, 但是编码出来的值也依赖于阶码字段的值是否为0.

根据exp的值, 被编码的值可以分成三种不同情况(1,2,3(ab)):

情况1:规格化的值

阶码字段被解释为以偏置(bias)形式表示的有符号整数. 而阶码的值是E=e-Bias, 其中Bias=2^{k-1}-1.

小数字段frac的二进制表示为0.f_{n-1}···f_1f_0, 而E=1+frac. 原因是小于1的frac全部都在情况二之中, 这样我们就相对偷来了一个多余位.

情况2:非规格化的值

非规格化数有两个用途:

  • 提供了表表示数值0的方法, 在情况1中, 由于E=1+frac就不能表示0. 而在情况2中, 有+0(所有位全为0)和-0(s位为1), 而在IEEE标准中, +0和-0有不同的含义.
  • 表示那些非常接近0.0的数.

情况3:特殊值

特殊值只出现在阶码全为1时, 当小数域全为0时, 得到的值表示为无穷(s=0为+∞, 反之亦然), 当小数域为非0时, 结果为NaN(Not a Number).


舍入(待补充)

浮点运算

IEEE中指定了一个简单的规则来指定加法和乘法的结果————把浮点数x和y看成实数, 而某个运算\odot定义在实数上, 计算将产生Round(x\odot y), 这是对实际运算的精确结果进行舍入后的结果.

有很重要的一点是, 浮点加法不具有结合性, 这是缺少的最重要的群属性.

例:

在单精度浮点下:
(3.14+1e10)-1e10 = 0
3.14+(1e10-1e10) = 3.14

又例:
假定以下代码片段:
x=a+b+c;
y=b+c+d;
编译器可能试图通过产生以下代码来省去一个浮点加法:
a=b+c;
x=a+t;
y=t+d;

另外重要的一点是, 浮点乘法在加法上不具有分配性.

例:
在单精度浮点下:
1e20*(1e20-1e20)=0.0
1e20*1e20-1e20*1e20=NaN

总结

在相同长度的无符号和有符号整数之间进行强制类型转换时, 大多数C语言实现遵循的原则的底层的位模式不变.

还有一个问题: ~x-1 = -x 是啥? 看来我又白学了…

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据