面试题算法分析(1)
写出下列算法题目的结果:
#include <iostream>
using namespace std;
int main()
{
float a=1.0f;
cout<<(int)a<<endl;//强制类型转换,舍去小数部分(截断),所以打印结果为1
cout<<(int&)a<<endl;// 见后面分析
cout<<boolalpha<<((int)a==(int&)a)<<endl;//boolalpha的功能是把bool值显示为true或false,因为一个是将浮点强制转换为整数,一个是将浮点解释为整数,所以二者不等,返回false
float b=0.0f;
cout<<(int)b<<endl;//因为0是一个特殊的数,它的浮点类型和整型存储在内存中是一样的。
cout<<(int&)b<<endl;
cout<<boolalpha<<((int)b==(int&)b)<<endl;
return 0;
}
编译器运行结果如下:
1
1065353216
false
0
0
true
主要疑惑在于1065353216这里,解释已经写在上面的注释里了.
int &这里表示引用,c++中引用表示别名,所以我认为这里是将原来内存中的浮点类型的a用整型来解释。这个时候就需要知道1.0f在内存里是怎样的,然后才能用int去解释这些字节。关于浮点格式在内存里的形式一直我认为都是比较难理解的,但是笔试中其实是经常出现的。
浮点型是用IEEE浮点标准表示的。其实就是我们所理解的科学记数法V=(-1)s x M x 2E的形式来表示一个数。对于float类型,二进制有32位,其中符号位1位,阶码8位,尾数23位;对于double类型数据,其二进制位为64位,符号位1位,阶码11位,尾数52位。
记住下面的表:
31 30-23 22-0
float 符号位 阶码 尾数
63 62-52 51-0
double 符号位 阶码 尾数
符号位:0表示正,1表示负
阶码:采用移码表示,对于float类型数据其规定偏置量为127,阶码有正有负,对于8位二进制,则其表示范围为-128-127,double规定偏置量为1023,其表示范围为-1024-1023。举个例子,对于float类型,若阶码的真实值为2,则加上127后为129,其阶码表示形式为10000010
尾数:有效数字,即部分二进制位(小数点后面的二进制位),因为规定M的整数部分恒为1,所以这个1就不进行存储了。
好的,回到我们原来的问题:
1.0f,整数部分为1,小数部分为0,写成二进制为1.0,由于规定尾数的整数部分必须为1,所以写成科学记数法还是1.0 * 20,阶码为0,加上127=127,转成二进制为0111 1111
尾数部分去掉1得到0,后面补零达到23位,则为0000 0000 0000 0000 0000 000
所以在内存中应该表示为(由高地址到低地址):
0 0111 1111 0000 0000 0000 0000 0000 000
写成字节的形式为:
00111111 10000000 00000000 00000000
然后用int去解释,得到1229+1228+1227+1226+1225+1224+1*223=1065353216得到正确答案。
参考资料 《深入理解计算机系统》