计算机浮点数 float 表示

这篇文章讲得比较浅显易懂,所以转一下。 必须对计算机原理的原码、反码、补码、移码有个清晰的认识,另外参考一下ieee754,否则也会有不明白的地方。括号内为本人看法或观点。 我想浮点数的实现与编译器也会有很大关系的。

 

(转)前两天仔细看了看, 觉得研究计算机如果不说说如何表示浮点数就太不厚道了.很多人也写过, 这里自己再写一道, 一是为了加深点印象, 第二是希望自己能写的深入浅出一点, 希望看过的人都能很容易看懂.

先说说32 位的 float型.
一个浮点数 X, 在计算机中表示为:
         X = a  *  2e  
 
这里 e 代表指数,  a 代表尾数,   在 计算机内部, 他们都是用二进制表示的. 其中 a 用二进制的科学表示法表示, 由于科学表示法第一位总是1 (0除外) , 所以第一位略去不计.  e 表示的时候, 因为要表示出负数, 所以 要加上127 ,  实际运算的时候要减去 127.

IEEE 规定, 32 位 float型被拆开成以下格式, 左边为高位 :
           0                                 0000 0000                     0000000 00000000 00000000
        最高位,第32位            第 31-24位,共8位                第23-1位            
        符号位                            指数位                                   尾数位
      0为正,1为负               -127~+128                        0~0x 7f ff ff

float 的范围是 -3.40282 * e38 ~ + 3.40282 * e38

一般在人看来是 十进制的数, 要转换成二进制. 十进制转二进制, 大于1 的部分就是除以2 取余, 小于1 的部分乘2 取整(上计算机原理课,讲了那么多东西就记得这句话了)
 比如 8.5  转换成二进制就是 1000.1 , 处理成这一步, 还要用科学表示法表示, 就成了 1.0001 * 23 ,  注意: 由于1.0001 第一个1 要去掉(科学计数法), 所以成了 0001 , 3 需要加上 127 就成了 130 (移码运算,原码加上2^n的结果再减1,其中n是数据位长度), 二进制就是 10000010 套用上面话就表示为:
     0  10000010 0001000  00000000 00000000
     16进制就是: 0x 41 08 00 00 , 一般来说 , intel 系列的CPU 字节顺序是Little-Endian(高字节放在后面), 因此在内存中的存放顺序是: 0x 00 00 08 41 , 这样就完成了一次浮点数的表示.

注意: 浮点数 0.0  在计算机中表示为 0x 00 00 00 00 .

那么浮点数的精度是怎么回事情呢? 当我们使用二进制表示 大于1 的部分的时候, 没有问题, 除以2,一直下去, 最后一位肯定不是1 就是 0; 那么小数部分呢?  举个例子, 比如 0.8
表示    0.8
             * 2
            1.6 - 1 = 0.6          
                             * 2
                             1.2 -1 = 0.2  - 0
                                            .* 2
                                             0.4 - 0
                                              *2     
                                             0.8 - 0
这样就循环了 就是说 0.8 的二进制 就是  0.11000 11000 ......  一直循环下去, 而我们计算机如果表示0.8只能取0后面的前25位(第一个1 略去, ^_^), 这就说明 如果是  0.80000000000000000000000001 , 它表示出来的值其实是和 0.8 一样, 所以我们比较float型的数字 用 a == b 其实是没有根据的, 一般都是 用 abs(a - b) < 0.000001 (0.000001应该是二进制吧?此处涉及到数学的实数常识,公式|a-b|<c  转换成  -c<a-b<c)之类就默认是相等.  所以这就出现了经典的精度问题.

那么 double型呢? 咱们可以照 float 型的葫芦 来画了.
double 型 只是说 取 64 位, 比float型的位 多一倍, 但是同样 逃不出精度的五指山.  :)
IEEE 规定 double 型 ,
    第64位             63-53                                                52-1
   符号位            指数位 ( -1023~+1024)                     尾数位

所以 double型的范围是  -1.79769 * e308 ~ +1.79769 * e308
多用了几位, 表示范围大了很多, 其实本质跟float型一样.

看来计算机是用来计算的, 一点都不假, 所谓机器智能, 也是人加上去的,  这就更不用怀疑了.

 

你可能感兴趣的:(c,float,编译器)