本帖最后由 rla540 于 2012-12-14 19:27 编辑
黑马程序员---浮点数内存表现形式 有符号整数和无符号整数内存转换还是比较简单的。 那么浮点数说白了就是小数又是怎么转化的呢?由于计算机的构造适宜存储整数,所在小数的转化相对来说要复杂一些 6.25怎么转换加工变成0x40c80000的呢? 首先把10进制小数转换成二进制小数,6用除二取余法转换二进制后为 110 0.25 用乘2取整法转换为二进制小数点后的数01 6.25 = 110.01 二进制的小数点向左移动2位,最高位保留为1变成1.1001,小数点向左移动1位指数就加1,移动了2位所以指数加2; 因为所有二进制小数经过这样的转换后最高位都只会为1,所以这个1就可以去掉。只留下1001当往回转换成十进制时只要再把这个1加上即可。 6.25是正数,所以最高位符号位为0,后边8位为指数位这个小数的指数为2 所以是 011111111 + 10 10000001 最后边23位由1001组成不足部分补0也就是 1001 0000 0000 0000 0000 000 最后把这32位二进制数全部输出看一下 01000000110010000000000000000000 再把这一串二进制数转换成16进制数得: 0100 0000 1100 1000 0000 0000 0000 0000 4 0 c 8 0 0 0 0 Ox40c80000那么在内存显示窗口中就表现为 00 00 c8 40 那么-6.25呢?只要把符号位从0变成1就行了: 1100 0000 1100 1000 0000 0000 0000 0000 C 0 C 8 0 0 0 0 那么在内存窗口中就显示为:00 00 C8 C0好我们验证下运行程序走 完全正确加10分,那么0.125又怎么转呢? 整数位为0所以不用转换了,只转小数部分转换后得二进制小数0.001,小数点向右移动3位得1.0 小数点向左每移一位指数就加1向右每移动一位自然就减1,所以指数部分得 01111111 + 11111101(-3的补码) = 01111100 因为是正数所以符号位为0, 小数点后为0所以最后面的23位全为0 0011 1110 0000 0000 0000 0000 0000 0000 3 E 0 0 0 0 0 0 所以内存中表示为 00 00 00 3E 看下程序是不是这样? 哈哈。正如所料 那么一个小数的小数部分转换二进制小数时乘不尽怎么办?那就一直乘下去,直到凑满23位为止。其余部分省略!那就拿0.025来说吧:不断乘2 得0.05, 0.1, 0.2, 0.4, 0.8, 1.6, 1.2, 0.4, 0.8, 1.6, 1.2, 0.4, 0.8。。。。。 0000 01 10 0110 0110 0110 0110 0110 0 小数点向右移动6位得1.10011001100110011001100 指数位 = 01111111 + 11111010(-6的补码) = 01111001 32位显示为 0011 1100 1100 1100 1100 1100 1100 1100 3 C C C C C C C 所以在内存窗口中应该显示为 cc cc cc 3c 和我们推出来的有点不一样?看看到底哪里不一样 0011 1100 1100 1100 1100 1100 1100 1100 我们推出得 0011 1100 1100 1100 1100 1100 1100 1101 实际显示的 我们发现只有最后末尾一位显示的不一样!最末尾的1100后边舍弃的数正好是1开头的,因此计算机对这个进制数进行了进位操作,类似于10进制中的四舍五入。 所以用浮点数存储小数都只会得到一个近似值! Double数据类型的转换和float类似。那么decimal呢?这个我还真不知道!看了下反汇编代码,计算机在背后做了一系列复杂的操作。这种转换方法,我们也没必要一一全部知道。通过浮点数转换这几个事例,只是说明。所有类型,在计算机中都是二进制数据。不管你是int , double, class ,struct,还是for , while, 还是方法等,都是数据,唯一不同的就是对这些数据的解释,运算,操作不同罢了!
|