float 存储

/*
 * 2021/2/4    15:33 qing
 */

/*
 * float 存储
 */

    浮点型变量在计算机内存中占用4字节(Byte),即32-bit。遵循IEEE-754格式标准。

    一个浮点数由2部分组成:底数 m 和 指数 e

        ±mantissa × 2exponent            /* 尾数×2指数 */

     (注意,公式中的mantissa 和 exponent使用二进制表示)

    底数部分 使用2进制数来表示此浮点数的实际值。

    指数部分 占用8-bit的二进制数,可表示数值范围为 0 - 255 。
            
              但是指数应可正可负,所以IEEE规定,此处算出的次方须减去 127 才是真正的指数。所以float的指数可从 -126 到 128.
    
    
    底数部分实际是占用 24-bit的一个值,由于其最高位始终为 1 ,所以最高位省去不存储,在存储中只有 23-bit。

    到目前为止, 底数部分 23位 加上指数部分 8位 使用了31位。那么前面说过,float是占用4个字节即 32-bit,那么还有一位是干嘛用的呢?  
    
    还有一位,其实就是 4 字节中的最高位,用来指示浮点数的正负,当最高位是 1 时,为负数,最高位是 0 时,为正数。

    浮点数据就是按下表的格式存储在 4 个字节中:

                Address+0    Address+1    Address+2    Address+3
    Contents    SEEE EEEE    EMMM MMMM    MMMM MMMM    MMMM MMMM     S: 表示浮点数正负,1为负数,0为正数

         E: 指数加上127后的值的二进制数

         M: 24-bit的底数(只存储 23-bit)

    主意:这里有个特例,浮点数为 0 时,指数和底数都为 0 ,但此前的公式不成立。 因为 2 的 0 次方为 1 ,所以, 0 是个特例。
    
    当然,这个特例也不用认为去干扰,编译器会自动去识别。


/*
 * -12.5在计算机中存储的具体数据
 */
                Address+0    Address+1    Address+2    Address+3
    Contents    0xC1         0x48         0x00         0x00

    由于浮点数不是以直接格式存储,他有几部分组成,所以要转换浮点数,首先要把各部分的值分离出来。

            Address+0   Address+1   Address+2   Address+3
    格式    SEEEEEEE    EMMMMMMM    MMMMMMMM    MMMMMMMM
    二进制  11000001    01001000    00000000    00000000
    16进制  0xC1        0x48        0x00        0x00

    S:为 1 ,是个负数。
    
    E:为 10000010  转为 10 进制为 130 , 130 -127 = 3 ,即实际指数部分为 3.

    M:为 10010000000000000000000 。 这里,在底数左边省略存储了一个 1 ,使用 实际底数表示为 1.10010000000000000000000
    
    把三个部分的值都拎出来了,现在,通过指数部分 E 的值来调整底数部分 M 的值。
    
    调整方法为:如果指数E为负数,底数的小数点向左移,如果指数E为正数,底数的小数点向右移。小数点移动的位数由指数E的绝对值决定。
    
    这里,E为正3,使用向右移3为即得: 1100.10000000000000000000


    这个结果就是 12.5 的二进制浮点数,将他换算成 10 进制数就看到 12.5 了,转换如下:

        小数点左边的 1100 表示为 (1 × 8) + (1 × 4) + (0 × 2) + (0 × 1), 其结果为 12 。

        小数点右边的 .100… 表示为 (1 × 2^(-1)) + (0 × 2^(-2)) + (0 × 2^(-3)) + ... ,其结果为 .5 。

        以上二值的和为 12.5 , 由于 S 为 1 ,使用为负数,即 -12.5 。

        所以,16进制 0XC1480000 是浮点数 -12.5 。

    /*
     * 内存数据: 01000001001000100000000000000000
     */
        第一步:符号位为 0 ,表示是正数;  
        
        第二步:指数位为 10000010 ,换算成十进制为 130 ,所以指数为 130 - 127 = 3;
        
        第三步:尾数位为 01000100000000000000000 ,换算成十进制为 (1+1/4+1/64);
        
        所以相应的十进制数值为: 2^3 * (1+1/4+1/64) = 8+2+1/8 = 10.125

/*
 * 浮点数装换成计算机存储格式中的二进制数
 */
    将 17.625 换算成 float型
    
    将 17.625 换算成二进制位: 10001.101  ( 0.625 = 0.5 + 0.125,  0.5 即 1/2,  0.125 即 1/8)
    
    再将 10001.101 向右移,直到小数点前只剩一位 成了 1.0001101 x 2 的 4 次方(因为右移了4位)。此时底数 M 和指数 E 就出来了:
    
    底数部分M,因为小数点前必为1,所以IEEE规定只记录小数点后的就好,所以此处底数为  0001101 。
    
    指数部分E,实际为 4 ,但须加上 127 ,固为 131 ,即二进制数 10000011
    
    符号部分S,由于是正数,所以S为 0.
    
    综上所述, 17.625 的 float 存储格式就是:    0 10000011 00011010000000000000000

    转换成16进制:0x41 8D 00 00

    还是占用了4个字节

/*
 * 8.25和120.5在内存中真正的存储方式
 */
    8.25 用二进制的科学计数法表示为

    :1.0001 * 2^3  按照上面的存储方式,符号位为 0 ,表示为正;指数位为 3 + 127 = 130,位数部分为 1.00001,
    
    故 8.25 的存储方式如下:  0xbffff380:    01000001000001000000000000000000

    分解如下: 0--10000010--00001000000000000000000  

    符号位为 0 ,指数部分为 10000010 ,位数部分为 00001000000000000000000

    

    120.5在内存中的存储格式如下:  0xbffff384 :    01000010111100010000000000000000

    分解如下 : 0--10000101--11100010000000000000000  

/*
 * 小数部分转换成二进制数
 */
    /*
     * 十进制的小数到二进制的转换
     */

        十进制的小数转换为二进制,主要是小数部分乘以 2 ,取整数部分依次从左往右放在小数点后,直至小数点后为 0 。
        
            例如十进制的 0.125 ,要转换为二进制的小数。

            将小数部分0.125乘以2,得0.25,然后取整数部分 0
                
                0.125 * 2 = 0.25        取 0
            
            再将小数部分0.25乘以2,得0.5,然后取整数部分 0

                0.125 * 2 = 0.25        取 0
                0.25  * 2 = 0.5            取 0
            
            再将小数部分0.5乘以2,得1,然后取整数部分 1

                0.125 * 2 = 0.25        取 0
                0.25  * 2 = 0.5            取 0
                0.5   * 1 = 1            取 1

            则得到的二进制的结果就是 0.001

    /*
     * 二进制到十进制的转换
     */

        二进制的小数转换为十进制主要是乘以 2 的负次方,从小数点后开始,依次乘以 2 的负一次方, 2 的负二次方, 2 的负三次方等。
        
            例如二进制数 0.001 转换为十进制。

            第一位为0,则0*1/2,即0乘以2负 一次方。
            
                小数点后

                第一位 0 * 1/2        即乘以 2 的负一次方
            
            第二位为0,则0*1/4,即0乘以2的负二次方。
    
                小数点后

                第一位 0 * 1/2        即乘以 2 的负一次方
                第二位 0 * 1/4        即乘以 2 的负二次方

            第三位为0,则0*1/4,即0乘以2的负三次方。
    
                小数点后

                第一位 0 * 1/2        即乘以 2 的负一次方
                第二位 0 * 1/4        即乘以 2 的负二次方
                第三位 1 * 1/8        即乘以 2 的负三次方

            各个位上乘完之后,相加, 0 * 1/2 + 0 * 1/4 + 1 * 1/8 得十进制的 0.125
                                    = 0  + 0 + 0.125
                                    = 0.125

猜你喜欢

转载自blog.csdn.net/xiaozhiwise/article/details/113766521