关于float
1 #include <iostream> 2 using namespace std; 3 4 void main() 5 { 6 float a = 1.0f; 7 cout << (int)a << endl; 8 cout << (int&)a << endl; 9 cout << boolalpha << ((int)a == (int&)a) << endl; 10 float b = 0.0f; 11 cout << (int)b << endl; 12 cout << (int&)b << endl; 13 cout << boolalpha << ((int)b == (int&)b) << endl; 14 }
这个题非常好,考查浮点数在计算机中的表示。
现在一般的计算机浮点数都是使用IEEE754标准,可到如下网站恶补:
https://en.wikipedia.org/wiki/IEEE_754-1985
通过查看IEEE754标准可知,单精度浮点数的表示为:
1位表示符号位,8位表示指数位(需加127的指数偏移),23位表示尾数位
所以 0.1562510 = 在计算机中的表示为
这样,上例中的浮点数 float a = 1.0f在计算机中的表示为
1.0 = 1.0x20
符号位 -> 0
指数部分 -> 0+127 = 01111111
尾数部分 -> 0
即 0011 1111 1000 0000 0000 0000 0000 0000 = 0x3f800000
所以
cout << (int)a << endl;
编译器的做法是取整数部分,即尾数部分1x2(127-127)=1
cout << (int&)a << endl;
编译器对引用的做法与强制类型转换又不一样,(int&)a相当于*(int*)&a,所以编译器并没有经过上述运算,直接将这个浮点数当作int类型来对待,故输出0x3f800000 = 1065353216。
所以其实引用与指针很相似,只不过不分配存储空间,且一经初始化就不可以再更改而已。它在传参时同样高效。
而float b = 0.0f是正0
在计算机中的表示为全0
即 0000 0000 0000 0000 0000 0000 0000 0000
所以cout << (int)b << endl; cout << (int&)b << endl;的结果都为0
=================================================================================================================
在论坛还看到一个例子,也很好
1 #include "stdio.h" 2 int main(void) 3 { 4 float a; 5 int b; 6 a=222222222; 7 b=(int)a; 8 printf("%d",b); 9 }
问题为:
输出结果为什么会是222222224而不是222222222。
高手的解答很详细:
这个问题需要一步一步来解释:
我们先看看单精度浮点数的格式:
31 30...23 22...0,bit[31]表示符号位,bit[30...23]表示指数位,bit[22...0]表示尾数位。还有一个默认的整数部分为1。
1. float a = 222222222.
222222222
=> 0b 1101 0011 1110 1101 0111 1000 1110 总共28个bit需去掉4位
=> 1.101 0011 1110 1101 0111 1000 1110 提取整数部分
=> 1.101 0011 1110 1101 0111 1001 [1110]去掉多余的部分且经过了round
开始组合
符号位:0
指数位:27+127(单精度偏置数)= 154= 0b 1001 1010
尾数位:0b 101 0011 1110 1101 0111 1001
最终结果:0b 0 1001 1010 101 0011 1110 1101 0111 1001
上面的结果就是a这个浮点数在内存中的二进制表示。
2. int b = (int)a.
0b 0 1001 1010 101 0011 1110 1101 0111 1001
=> 1.101 0011 1110 1101 0111 1001 乘以 2^27
=> 0b 1101 0011 1110 1101 0111 1001 0000 正数
=> 222222224
=================================================================================================================
与上类似,double型的数也按上述规则转化,只不过数据长度稍有不同,如下:
以double 3.5为例:
3.510 = 11.12 = 1.112 x 2 1
=>
符号位 -> 0
指数部分 -> 1+1023 = 100 0000 0000
尾数部分 -> 11 -> 11 0000 ...
组合起来即为 0100 0000 0000 1100 ... = 0x400c0000 00000000
little endian的计算机表示为 00 00 00 00 00 00 0c 40