浮点数
1.浮点数家族包括:float、double、long double。
2.常见的浮点数:3.14159、1E10、9.0
浮点数存储例子
我们通过这样的一个例子来展开了解浮点数的存储规则。
如下:
#include<stdio.h>
int main()
{
int n = 9;
float* pF = (float*)&n;
printf("n的值为:%d\n", n);
printf("*pF的值为:%f\n", *pF);
*pF = 9.0;
printf("n的值为:%d\n", n);
printf("*pF的值为:%f\n", *pF);
return 0;
}
我们检查一下思考的结果是否正确:
在解释之前,我们需要了解浮点数的存储规则
浮点数的存储规则
根据国际IEEE标准,任何一个浮点数V可以写成以下形式:
- (-1)^ S * M * 2^E
- (-1) ^S表示符号位,当 S = 0,V为正数,S = 1,V 为负数
- M表示有效数字,大于等于1,小于2
- 2 ^ E 表示指数位
举例来说,对于十进制的 5,二进制为:101.0,小数点向前移动2位,变成了
1.01 × 2^2.
其中,S = 0,M = 1.01, E = 2
- IEEE 754规定:
对于32位浮点数,对于最高的1位是符号位S,接着8位是指数E,剩下的23位是有效数字M - 对于64位浮点数,对于最高的1位是符号位S,接着11位是指数E,剩下的52位是有效数字M
特别规定:
- 对于M
因为 1≤M<2,因此M总是可以写成1.xxxxxx,为了多保留有效数字,计算机保存M时,1被省略,最后再加上1,即计算机只保存了xxxxxx。 - 对于E
因为E是无符号整数,但我们知道 E 可以出现负数的,因此我们存入E需要加上中间值:- 如果E为8位,那么这个中间值是127
- 如果E 为11位,那么这个中间值是1023
取出E,我们分三种情况:
- E不全为0或1:计算值减去127(1023),再将M加上1
- E全为0:E 等于1-127(1023)即为真实值,有效数字不再加上1
- E全为1:这是如果M为全0,表示正负无穷大(正负号取决于)
了解这些,我们再回到例题:
#include<stdio.h>
int main()
{
int n = 9;
float* pF = (float*)&n;
printf("n的值为:%d\n", n);
printf("*pF的值为:%f\n", *pF);
*pF = 9.0;
printf("n的值为:%d\n", n);
printf("*pF的值为:%f\n", *pF);
return 0;
}
我们按顺序看每一行打印的值:
-
n = 9是整形,因此打印的第一个值是9
-
pF是浮点数型指针变量,计算机会从浮点数的视角来解读n存储的值。
9的补码为:0 00000000 0000000000000000001001
S = 0,E = 1-127 = -126,M = 0000000000000000001001,因为E为全0,M不加1
结果为:0.0000000000000000001001×2^-126,由于浮点数只能打印到小数点后6位,所以结果为0.000000 -
9.0转化成二进制为:1001.0 即:
(-1) ^ 01.001 ×2^3,可知S = 0,E = 3+127 = 130 ,M = 00100000000000000000000
9.0存储在计算机最终结果为:
0 10000010 00100000000000000000000
从整形的角度看结果为:1,091,567,616 -
从浮点数的视角的解读9.0打印的结果为9.0