一、浮点类型要点
- 常见浮点型:float(四字节)、double(八字节)
- 浮点类型没有无符号类型,也就是说浮点型内存中一定有符号位
- 与浮点型有关的操作不会发生整型提升(只在char与int之类的整型之间),但是要注意隐式类型转换
- 浮点型数据不能作 == 或 != 比较,只可区间比较(解释在下文)
二、浮点型储存规律
- 通过例子了解浮点型与整型的差异:
int main()
{
int n = 9;
float *pf = (float *)&n;
printf("第一次n值为:%d\n", n);
printf("第一次*pf值为:%f\n", *pf);
*pf = 9.0;
printf("\n第二次n值为:%d\n", n);
printf("*第二次pf值为:%f\n", *pf);
system("pause");
return 0;
}
第一次输出 n 的值与解引用 *pf 的值不同,说明了浮点型变量对内存读取数据的方式与整型不同(我的上篇博客详细讲解了数据在内存的存在形式与数据类型的关系);
第二次通过解引用令变量 n 重新赋值 9.0,出现了 int 类型的变量 n 以整数形式输出并不是9的结果,进一步佐证了数据在内存的存在形式与变量的数据类型并无关系
-
存储原理
我们知道,无符号整型 在内存中直接开辟32 bit位存储二进制数据;有符号整型 将32位的第一位作为符号位,剩余的31位存放二进制数据;但是对于浮点型数据 来说,除了符号位外,还有两种二进制数据:一种小数点前的数值,一种小数点后的数值。现在计算机采用了国际标准IEEE754,严谨的存储了浮点数据:
任一个小数可以表示为:(-1)^S * M * 2^E 这种形式S 符号位,当s=0,值为正数;当s=1,值为负数;
M 基数位,对于二进制来说,这个值大于2小于1,那么在存放时,规定省略基数的前半部分(都一样),只存放小数点后的数据;
E 指数位, 在数学概念上,指数位是有正负之分,而内存中指数位区域并未专门设置符号位,而是通过 ±中间数 实现;float类型中指数位有8位,取值范围[0,255],中间数127 操作后的实际范围是[-127,128];double类型中指数位有11位,取值范围[0,2047],中间数1023 操作后的实际范围是[-1023,1024].
-
float类型
对于float类型,在内存中将四字节32位bit空间如下图多分,一个小数在存到内存时,先转换为二进制数,再将这个数以科学计数法表示,得到该数的正负、基数和指数,并按规则写入内存
例如十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,s=1,M=1.01,E=2+127=129
按float保存后:1 10000001 01000000000000000000000
-
double类型
-
要点4解释(浮点型精度)
E全为0浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为
0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
正是由于浮点型数据有这样的特殊性,不能直接比较E全为1
这时,如果有效数字M全为0,表示±无穷个最大值(正负取决于符号位s);
三、例题解释
-
int 型变量 n 一开始存放的是整型数值 9,也就是说该变量空间内是9的32位二进制:0000…0000 1001;
按 %d整型形式 输出则按原反补输出,出现第一个结果9;
按 %f浮点型形式输出则按指数位,基数位转换输出:指数位全为0,故输出结果为0.
-
int 型变量 n 的空间内容被解引用放入了浮点型9.0的二进制数据:符号位为0,指数位为127+3,基数位为0010…0000 即为:0 10000010 00100000000000000000000;
按 %d整型形式 输出则按原反补输出,出现第一个结果1,091,567,616;
按 %f浮点型形式 输出则按指数位,基数位转换输出结果为9.00000.