那么好了好了,宝子们,今天给大家介绍一下 “数据在内存中储存” 的来龙去脉---浮点数,来吧,开始整活!⛳️
一、数据类型家族(浮点数)
家族成员:float,double,long double
二、浮点数在内存中的存储
1.抛砖引玉 :
通过下面的例题一,我们来引入浮点数在内存中的存储是怎么样的?
#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
int n = 9;
float* p = (float*)&n;
printf("n的值为:%d\n", n);
printf("p的值为:%f\n", *p);
*p = 9.0;
printf("n的值为:%d\n", n);
printf("p的值为:%f\n", *p);
return 0;
}
当我们没有运行,咱们可以猜想一下这4个结果分别是什么呢?
我相信很多小伙伴和我当时想的一样,那么就是:
9
9.000000
9
9.000000
是这个样子的,但是我们看一下实际运行结果是什么样的?
结果和我们想的不一样,错了一半,为什么呢?我们接下来就开始解释一下这个浮点数在内存中到底是怎样存储的?
三、浮点数存储的关键表达式:浮点数(v)=(-1)^S*M*2^E
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
但是别看的这么简单,还有一个特别需要注意的点,就是E和M的储存都有特殊情况:
0 01111110 00000000000000000000000
四、首尾呼应(对前面例题的解释)
对前半部分的分析:
int n = 9;
float* p = (float*)&n;
printf("n的值为:%d\n", n);//9(在这一步我们以整数的形式放进n里面,再以%d整形来打印出来,完全没有问题,答案就是9)
printf("p的值为:%f\n", *p);//0.000000
/*9------>0 0000000000000000000000000001001(二进制)
当我们以浮点数的视角来打印出来的时候,我们要分别求出来S M E。
0 00000000 00000000000000000001001
S E M
1.当E是全0的时候,E=1-127即为真实值。
2.有效数字M不再加上第一位的1,而是还原为
0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
浮点数v=(-1)^0*0.00000000000000000001001*2^(-126)
因为以%f的形式打印出来浮点数,最终的结果只有小数点的后6位 : 0.000000*/
对后半部分的分析:
*p = 9.0;
printf("n的值为:%d\n", n);//1091567616
/*因为上一部分的代码*p是浮点数,所以我们以浮点数的形式储存9.0。
9.0
1001.0=1.001*2^3
又因为9.0是正数,所以s=0
9.0==(-1)^0*1.001*2^3
内部的储存结果如下:
0 10000010 00100000000000000000000
S E M
当我们以整形的形式打印出来的时候,又因为它是个正数,所以说打印出来的时候正数的原码反码补码相同:
最终的结果直接就是他:01000001000100000000000000000000
然后再以二进制读出来:1091567616*/
printf("p的值为:%f\n", *p);//这个地方等于9.000000没有疑问
好了,今天的分享就到这里了
如果对你有帮助,记得点赞+关注哦!
我的主页还有其他文章,欢迎学习指点。关注我,让我们一起学习,一起成长吧!