目录
一,提出问题
分析代码
#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("n的值为:%F\n", *pFloat);
return 0;
}
运行结果:
为什么会得到这样的结果呢?
二,浮点数存储规则
二进制浮点数表示形式
(-1)^ S * M * 2 ^ E
(-1)^ S 表示符号位 当S=0, V 为正数 S=1时候 V为负数
M表示有效数字,大于等于1,小于2
2^E表示指数为
例:
十进制2.5, 写出二进制是 10.1 相当于 (-1) ^ 0 *1.01 * 2 ^ 1
那么按照公式可以得到 S = 0 M = 1.01 E = 1
十进制2.5, 写出二进制是 -10.1 相当于 (-1) ^ 1 * 1.01 * 2 ^ 1
那么按照公式可以得到 S = 0 M = 1.01 E = 1
IEEE 754规定
对于32位浮点数(float单精度浮点类型类型) 最高的1位是符号位S 接下来的8位是指数E 剩下的23位为有效数字M
对于64位浮点数(double双精度浮点类型类型) 最高的1位是符号位S 接下来的11位是指数E 剩下的52位为有效数字M
IEEE 754特别规定
指数E的特殊情况
首先,E为一个无符号整数(
unsigned int) 这意味着,如果E
为
8
位,它的取值范围为
0~255
;如果
E
为
11
位,它的取值范围为
0~2047
。但是,我们 知道,科学计数法中的E
是可以出 现负数的,所以IEEE 754
规定,存入内存时
E
的真实值必须再加上一个中间数,对于
8
位的
E
,这个中间数 是127
;对于
11
位的
E
,这个中间数是1023
。比如,
2^10
的
E
是
10
,所以保存成
32
位浮点数时,必须保存成
10+127=137,即 10001001。
然后,指数E从内存中取出还可以再分成三种情况:
E不全为0或不全为
1
这时,浮点数就采用下面的规则表示,即指数
E
的计算值减去
127
(或
1023
),得到真实值,再将 有效数字M
前加上第一位的
1
。
E全为0
这时,浮点数的指数
E
等于
1-127
(或者
1-1023
)即为真实值,
有效数字
M
不再加上第一位的
1
,而是还原为
0.xxxxxx
的小数。这样做是为了表示
±0
,以及接近于
0
的很小的数字。
E全为1
这时,如果有效数字
M
全为
0
,表示
±
无穷大(正负取决于符号位
s
)
三,解题思路
请看注释.....
int main()
{
int n = 9;
//00000000000000000000000000001001 - 9的补码
//
//0 00000000 00000000000000000001001
//E = 1-127 = -126
//M = 0.00000000000000000001001
//(-1)^0 * 0.00000000000000000001001 * 2^-126
//
float* pFloat = (float*)&n;
printf("n的值为:%d\n", n);//9
printf("*pFloat的值为:%f\n", *pFloat);//0.0
*pFloat = 9.0;//以浮点数的视角,存放浮点型的数字
//1001.0
//1.001 * 2^3
//(-1)^0 * 1.001 * 2^3
//S=0
//E=3
//M=1.001
//0 10000010 00100000000000000000000
//
printf("num的值为:%d\n", n);//1,091,567,616
printf("*pFloat的值为:%f\n", *pFloat);//9.0
return 0;
}
正是因为读取的方式不同才导致不同的结果!!!!