计算机组成原理–浮点数表示

先人有云:

 
浮点运算,深奥、晦涩、难懂!我们对浮点运算的所有想当然的假设可能都是不靠谱的。正如Herb Sutter所说,世界上的人可以分3种:
  ● 一种是知道自己不懂浮点运算(我就是);
  ● 一种是以为自己懂浮点运算;
  ● 最后一种是极少的专家级人物,他们想知道自己是否有可能最终完全理解浮点运算。

而以下胡乱文字就为记录其特性而生。

相对小数点固定的定点数,浮点数自然就是小数点可以浮动的数。这种数可以非常方便地表示诸如0.00000000001和233333333333.0这样的数。为了能够在各种机器上都能表示同一个数,有个叫IEEE754的标准做出了明确定义。

浮点数利用科学计数法来表达实数,利用指数达到了浮动小数点的效果,从而可以灵活地表达更大范围的实数,其结构包括一个尾数,一个基数,一个指数以及一个表示正负的符号来表达实数。(有些时候尾数被称作有效数字)其中float型占用4个字节空间:1位符号,8位指数,23位尾数 ; double型占用8个字节:1位符号,11位指数,52位尾数

同样的数值可以有多种浮点数表达方式,比如 101.11 可以表达为 10.111 × 10^1,0.10111 × 10^3 或者 1.0111 × 10^2。因为这种多样性,有必要对其加以规范化以达到统一表达的目标。做出的规定即是整数位仅保留一个数字,同时因为这个数字一定是1(不是1说明小数点移过头了),也可以省略掉。显然,尾数越长精度和表示范围就越高。超出范围时会产生溢出(Flow),一般称大于绝对值最大的数据为上溢,小于绝对值最小的数据为下溢,分别会被认定为无穷和零。

  IEEE754标准规定一个实数V可以用:  V=(-1)s×M×2^E的形式表示,说明如下:
  (1)符号s(sign)决定实数是正数(s=0)还是负数(s=1),对数值0的符号位特殊处理。
  (2)有效数字M是二进制小数,M的取值范围在1≤M<2或0≤M<1。
  (3)指数E(exponent)是用移码表示的2的幂,它的作用是对浮点数加权。

为了强制定义一些特殊值,IEEE标准通过指数将表示空间划分成了三大块:

  【1】最小值指数(所有位全置0)用于定义0和弱规范数
  【2】最大指数(所有位全值1)用于定义±∞和NaN(Not a Number)
  【3】其他指数用于表示常规的数。

这样就可以表达出诸如0/0和0*∞的情况而不会把电脑炸掉。

非规范数是啥?就是当我们遇到了特别小的数字,小到指数用完了都表示不出来。 比如0.0001 × 2-125,表达为规范浮点数则为 1.0 × 2-129,超过了2^-126的限制。为了解决此类问题,IEEE 标准中引入了非规范浮点数。规定当浮点数的指数为允许的最小指数值,尾数不必是规范化的。比如上面例子中的差值可以表达为非规范的浮点数 0.001 × 2-126。

很多小数根本无法在二进制计算机中精确表示(比如最简单的 0.1)由于浮点数尾数域的位数是有限的,为此,浮点数的处理办法是持续该过程直到由此得到的尾数足以填满尾数域,之后对多余的位进行舍入。事实上,只有很少一部分十进制小数具有精确的二进制浮点数表达。再加上浮点数运算过程中的误差累积,结果是很多我们看来非常简单的十进制运算在计算机上却往往出人意料。这就是最常见的浮点运算的”不准确”问题。

对于单精度数,由于我们只有 24 位的尾数(其中一位隐藏),所以可以表达的最大指数为 2^24 – 1 = 16,777,215。(特别的,16,777,216 是偶数,所以我们可以通过将它除以 2 并相应地调整指数来保存这个数,这样 16,777,216 同样可以被精确的保存。)因此一些超过2^24的int型数将无法被转换成float型(但其尾部全是0时是例外)。

发表回复

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