《编码》之定点数与浮点数

    《编码》真是一本不错的书,从灯泡通信、继电器、二进制层层深入,再到加法器、汇编、处理器。全部连了起来,精妙啊,可惜现在才看到这本书,不过也为时不玩。

     23章中讲到了定点数与浮点数,所以这里做下记录吧。

1.定点数

     所谓的定点数,就是只小数点的位置总是在数的某个特定的位置,也就是有效位数是固定的。像书中所举的用压缩BCD(用四个位来表示0~9)保存数值就是只留两位小数,另外还有1位是符号位,用来标识数的正负。例如:

00010100 00110010 01010001 00100000 00100101 00000001 00010001
-   4    3   2    5   1    2   0.    2   5 +   1.    1   1

     上面两个二进制就分别表示-4325120.25和1.11。

2. 浮点数

     计算机中的浮点格式是借助二进制数实现的科学计数法形式。

2.1 科学计数法

     科学计数法将每个数表示成有效位与10的幂的乘积形式,这样子就可以避免写一长串的0,采用科学计数法,数490,000,000,000可以记为:4.9*10^{11},而数0.00000000026可以记为:2.6*10^{-10}。其中4.9和2.6被称作小数部分或者首数,而在计算机术语中这一部分被称为有效数(significand),11和-10则是指数(exponent)部分。

     为了便于操作,一般规定有效数的取值范围是大于或等于1且小于10。这种写法有时被称为科学计数法的规范化式(normalized)

2.2 浮点格式(floating-point notation)

    浮点格式是对小数存储除了定点格式外的另一种格式,它是基于科学计数法的。在十进制数中,小数点右边的数字与10的负整数次幂相关联,而在二进制数中,二进制小数点右边的数字则和2的负整数次幂相关,例如101.1101就可以表示为:

                                     1*2^{2}+0*2^{1}+1*2^{0}+1*2^{-1}+1*2^{-2}+0*2^{-3}+1*2^{-4}

     在二进制的科学技术法中,规范化式的有效数应该大于或等于1且小于10(二进制中的2),因此101.1101的规范化式为:

                                                                                 1.011101_{2}*2^{2}

     这个规则暗示了这样子一个现象:在规范化式二进制浮点数中,小数点的左边通常只有一个1,除此之外没有其他数字

2.3 IEEE浮点数标准

     当代大部分计算机和计算机程序在处理浮点数时所遵循的标准都是由IEEE与1985年制定的,ANSI/IEEE std 754-1985称作IEEE二进制浮点数算术预算标准。该标准定义了两种基本格式:以4个字节表示的单精度格式和以8个字节表示的双精度格式,即我们常见的float的double。

     单精度格式的4个字节可以分为三个部分:1位的符号位(0代表正数,1代表负数),8位用作指数,最后的23位用作有效数字,如下所示:

s = 1 位符号 e = 8 位指数 f = 23 位有效数

    这里23位有效数实际上指的是23位小数部分,因为规范化式二进制小数点左边固定只有一位1,所以虽然存储的只有23位,但仍然称其精度为24位。

    8位指数部分的取值范围是0~255,称为偏移(bias)指数,意思是对有符号指数,为了确定其实际所代表的值必须从指数中减去一个值——称作偏移量(bias),对於单精度浮点数,其偏移量为127,指数范围为1~254,而0和255用于特殊的目的。

     对于一个特定的数,可以用s、e以及f来描述:

                                                                           (-1)^{s}*1.f*2^{e-127}

    对于浮点数的e和f,有四种特殊情况

  1. 如果e=0且f=0,则该数为0,。在这种情况下,通常把32位都设置为0以表示该数为0.但是符号位可以设置为1,这种数可以解释为负0。负0可以用来表示非常小的数,这些数极小以至于不能在单精度格式下用数字和指数来表示,但它们仍然小于0。
  2. 如果e=0且f != 0,则该数是合法的,但不是规范化的,这类数可以表示为:(-1)^{s}*0.f*2^{-127}
  3. 如果e=255且f=0,则该数被解释为无穷大或者无穷小,这取决于符号位s的值。
  4. 如果e255且f != 0,则该值被解释为“不是一个数”,通常被缩写为NaN(not a number)。NaN用来表示未知的数或非法操作的结果。

     单精度浮点格式下,可以表示的规格化的最小正、正负二进制数分别是:

                                                             1.00000000000000000000000_{2}*2^{-126}

                                                             1.11111111111111111111111_{2}*2^{127}

      分别对应e=1和e=254的情况,在十进制下,两个数近似等于:

                                                                       1.175494351*10^{-38}

                                                                       3.402823466*10^{38}

      这两个数就是单精度浮点数的有效表示范围了。

      对双精度浮点数(double-precision floating-point format),其结构如下所示:

s = 1位符号位 e = 11 位指数位 f = 52 位有效数

       双精度浮点数的指数偏移量是1024(2^{e-1}-1 = 2^{10} - 1)所以该格式存储的数可以表示为:

                                                                    (-1)^{s}*1.f*2^{e-1023}

       表示范围为:

                                              2.2250738585072014*10^{-308} ~ 1.7976931348623158*10^{308}

3. 定点数 VS 浮点数

       由于定点数用4个位表示一个十进制的数,所以对于23000000000000这种后面带很多0的数,它将会用很多的位去保存,而浮点数则不需要。对于定点数,还需要预先知道小数点的位置是在哪里(即保留多少位有效数字)。

      而对于浮点数,最大的问题就是精度的问题,因为有效数的原因,单精度浮点数的精度为1/2^{24}或1/16777216,所以在单精度浮点格式下16,777,216和16,777,217将会被表示成同一个数,也就是:

                                                                   1.00000000000000000000000_{2}*2^{24}

       而下一个二进制浮点数可能表示的最大有效数是16,777,218,即为:

                                                                    1.00000000000000000000001_{2}*2^{24}

       例如,我们无法用浮点数的格式表示出0.1和0.9,而只能无限接近。

       所以当我们对数据的精度要求很高不能用近似比如银行中的钱款数目,用定点数就会好一些。

       并且上面讲到的负0的情况,也会导致我们对浮点数是否为0的判断不能像整数那样子,而需要用这种方式:-0.00001 < a && a < 0.00001来判断。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章