我们先来看两行代码:
float x=1.75,y=1.75;
cout<<(int)x<<" "<<(int&)y<<endl;
输出为:1 1071644672
首先呢,我们来看一下浮点数的格式:
float是单精度32位,所以呢:
- 符号位 (Sign):0代表正数,1代表为负数;
- 指数位 (Exponent):用于存储科学计数法中的指数数据,指数的数值要加上127,如果指数本来是3,那么要换成130来存储;
- 尾数部分 (Mantissa):采用移位存储尾数部分,因为M的值一定是1<= M <2,所以它绝对可以写成1.xxxxxxx的形式,所以规定M在存储时舍去第一个1,只存储小数点之后的数字,这样做节省了空间。举例子:
用二进制的科学计数法表示 1000.1,可以表示为1.0001 * 23
用二进制的科学计数法表示 1110110.1,可以表示为1.1101101 * 26
任何一个数的科学计数法表示都为1. xxx * 2n ,尾数部分就可以表示为xxxx,由于第一位都是1嘛,干嘛还要表示呀?所以将小数点前面的1省略。
举个例子,浮点数-3.75,先将其转换成2进制的,则为-11.11,可以写成-1.111*2^1,所以符号位是1,加127等于128,指数位是1000 0000,尾数位是111 0000 0000 0000 0000 0000(就是3个1,然后后面20个0,一共23位)。
11000 0000 111 0000 0000 0000 0000 0000
那么1.75呢?1.75写成二进制就是1.11*2^0,所以符号位是0,指数位0+127=127,是0111 1111,尾数位是110 0000 0000 0000 0000 0000(2个1,后面21个0,一共23位),把这几部分写在一起就是:
0011 1111 1110 0000 0000 0000 0000 0000
这个浮点数,在内存里存储的格式就是这样。如果我们把它当做整数来读取,那会是多少呢?
输出为:1071644672
是不是感觉很巧啊,哈哈,发现点什么了嘛?
(int)x 强制类型转换,是将浮点数x为参数构造整数(即float转换为int)
(int &)y 则是告诉编译器将y看成int对待(内存里的数据不做任何转换),所以(int &)x值为1071 644 672。
至于(int*)的话,我就不多说啦,就是强制转换成整型指针,一般人们容易混淆的是(int)和(int&)这两个。
补充:浮点数0.0是比较特殊的,它并不按照上面说的浮点数的格式存储,浮点数0.0在内存里的存储是000.....000(全零)。