首先,先来看一下以下这个程序:>
在学习的时候, 我给出的答案是非常的单纯的9 9.0 9 9.0,然而,当程序跑起来之后:>
要分析以上程序, 首先得了解浮点数在内存中的存储。
对于二进制浮点数, 根据国际标准IEEE(电气和电子工程协会) 754, 任意一个二进制浮点数V都能表示为以下形式:>
*(-1) ^S * M 2 ^E
其中(-1)^S为符号位,当s = 0 时,V为正数, 当浮点数s = 1 , V为负数.
M为有效位, M>=1且M < 2
2 ^E次方表示指数位
举个例子:>
例如十进制浮点数 5.5,我们将其转换为二进制就为:>
101.1 //这里是 .1的原因是此处1的权重是2 ^-1次方,即为0.5.而我们用上面V的格式,就能这样写:>
*(-1)^0 1.011 * 2 ^ 2
即S = 0; M = 1.011; E = 2;
对于-5.5,用上面V的格式, 就可以表示为
*(-1)^1 (1.011) * 2 ^2;
对于浮点数在内存中的存储,有以下规定
对于单精度浮点数而言
对于双精度浮点数:>
此外还有一些规定: 因为M总是>=1 小于2, 即M永远是等于1的整数, 因此,在内存中存放时,只会存小数位,例 5.5
可以表示为**(-1)^0 1.011 * 2 ^ 2*, M = 1.011。 但我们存储的收, 只会存储011, 而当我们去使用的时候, 才会把1给补上。
对于指数E而言, 其首先是一个unsigned int类型的数, 因此它的范围为 0 ~ 255(8bit) 或者 0 ~2047(11bit)
而用科学计数法表示的时候, 难免会出现E为负数的情况 例如 十进制0.5 用二进制数表示为:>
1*10 ^-1 又E的范围大于等于0, 因此, 规定存入内存E的真实值必须再加上一个中间数, 即加127 (8bit) 或1023(11bit)后,再存入内存
例如刚才的-1.,保存成32位浮点数时, 保存为 -1 + 127 = 126即
01111110
此外, 指数E还有以下规定:>
若E的值不全为1或0, 则E的真实值就为内存中存储的值减去127(或1023),再将有效数字M前加上第一位的一。
例如刚才的0.5 二进制V表示为:>
1.0*2 ^ -1 此处E为-1, M为1.0,因此存进内存中的数据为
0 01111110 00000000000000000000000
若E中存储的数据为全0时, 那么我们想一下, 则将是一个多么小的数字!,即2^ -127次方, 因此, 规定如下:>
当E中存储的数据为全0时, 其指数E的真实值为 1 - 127(或1023), 且有效数字M前不再加上一, 而是加上0, 以此来表示一个接近0的数。
当E中存储的数据为全一时, 那么E的真实值为128(8bit), 那么2^E次方是一个非常大的数字, 因此,V表示为正负无穷大。
现在我们重新回到开头的第一道例题:>
#include <stdio.h> int main() { int n = 9; float* pFloat = (float*)&n; printf("n的值为:%d\n", n); printf("*pFloat的值为:%f\n", *pFloat); *pFloat = 9.0; printf("num的值为:%d\n", n); printf("*pFloat的值为:%f\n", *pFloat); return 0; }
再看一下第二部分:>
以浮点数的形式将n改成了9.0,那么9.0的二进制表示为:>
1001.0即1.001*2^3 那么S = 0; E = 3 + 127 = 130; M = 0.001.即
0 1000 0010 00100000000000000000000
因此以整数的形式来看,这个数据为:>
以浮点数的形式来看, 当然是9.0了。