一道面试题引发的问题:浮点数和整数在计算机种的存储方式

1.先看题目:

    给出下面代码的输出:

  

[html]  view plain copy
  1. float a = 1.0f;  
  2. cout << (int)a << endl;  
  3. cout << (int&)a << endl;        // (int&)a , 是什么意思呢?   
  4. cout << boolalpha << ( (int)a == (int&)a ) << endl;  
  5.   
  6. float b = 0.0f;  
  7. cout << (int)b << endl;  
  8. cout << (int&)b << endl;  
  9. cout << boolalpha << ( (int)b == (int&)b ) << endl;  
    结果也给你吧:

[html]  view plain copy
  1. 1  
  2. 1065353216  
  3. false  
  4. 0  
  5. 0  
  6. true  
    如果不知道(int&)a是什么意思,你可能会猜测它表示变量a的地址转化为十进制表示(地址一般是十六进制表示的,int将其强制转化为十进制)。这样的话,第二行每次打印出来的数应该是不同的,但是第二行打印的始终是1065353216;而且按上面的理解,(int&)b打印出来也不应该是0。

    其实,(int&)a表示把a地址处的4个字节强制转换成长int型4个字节,那么为什么1.0f存储后转为int变成1065353216呢?这就涉及到整型和浮点型数在计算机里存储方式的问题了,见下。


2.浮点数和整数在计算机种的存储方式

   (1)整数的存储方式:计算机用二进制来表示整数,最高位是符号位;

   (2)浮点数的存储方式:

    以intel的处理为例,并且方便起见,这里只以float型为例——从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float是32位的,double是64位的,所以double能存储更高的精度。由于Intel CPU的架构是Little Endian(请参数机算机原理相关知识),所以它是按字节倒序存储的但是这里先不考虑逆序存储的问题(省得被搞晕了)后面你会发现存储顺序不影响我们这里要讨论的转换问题

    首先了解如何用二进制表示小数(也就是如何把十进制小数转化为二进制表示):
    举一个简单例子,十进制小数 10.625
        1)首先转换整数部分:10 = 1010b
        2)小数部分0.625 = 0.101b 
        (用“乘2取整法”:0.625*2=1.25,得第一位为1,0.25*2=0.5,得第二位为0,0.5*2=1, 得第三位为1,余下小数部分为零,就可以结束了)
        3)于是得到 10.625=1010.101b
        4) 类似十进制可以用指数形式表示:
            10.625=1.0625*(10^1)
    所得的二进制小数也可以这样指数形式表述:
        1010.101b=1.010101 * (2^3)
    也就是用有效数字a和指数e来表述: a * (2^e),现在我们要的尾数和指数都出来了。显而易见,最高位永远是1,所以这个1我们还有必要保留他吗?当然没有必要!好的,删掉他。这样尾数的二进制就变成了:010101*(2^3)(注意前面是有小数点的,但是既然一定有小数点,那这个小数点也是没有必要保存的)。
    用一个32bit的空间(bit0~bit31)来存储这么一个浮点数,分配存储空间如下:
    bit0~bit22 共23bit,用来表示有效数字部分,也就是a,本例中补全后面的0之后 a变为010 1010 0000 0000 0000 0000
    bit23~bit30 共8个bit,用来表是指数,也就是e,范围从-128到127,实际数据中的指数是原始指数加上127得到的,如果超过了127,则从-128开始计,所以这里e=3表示为130
    bit31 为符号位,1表示负数,这里应该为0
把上述结果填入32bit的存储器,就是计算机表示小数10.625的形式。

    注意这个例子的特殊性:它的小数部分正好可以用有限长度的2进制小数表示,因此,而且整个有效数字部分a的总长度小于23,因此它精确的表示了10.625,但是有的情况下,有效数字部分的长度可能超过23,甚至是无限多的,那时候就只好把后面的位数截掉了,那样表示的结果就只是一个近似值而非精确值;显然,存储长度越长,精度就越高,比如双精度浮点数长度为64位,1位符号位,11位指数位,52位有效数字。


3.回到原题

    回到原题,我们的1.0f按以上方式存储到计算机是什么样子的呢?简单重复下刚刚的步骤:

    1.0f=1.0b,转化为指数形式为:1.0*(2^0),去掉首位置的1和小数点,补全0之后,bit0~bit22位如下:000 0000 0000 0000 0000 0000;

    指数原本为0,但是要加上127,所以bit23 - bit30位如下:0111 1111;

    1.0f为整数,所以符号位为0

    最终1.0f在计算机中存储为:0011 1111 1000 0000 0000 0000 0000 0000,转化为十进制试下,看看是不是1065353216?!(*^__^*) 

    至于(int&)b,0在计算机中存储为32位全0,这是约定的(你会发现0没法像2中方法存储)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值