👦个人主页:努力努力再努力
👦个人介绍:一名机械专业的c++爱好者
欢迎大哥哥姐姐们评论、收藏、关注!
我只相信命运是掌握在自己手中的希望各位哥哥姐姐们留下宝贵的批评,您的建议就是我前进的动力
这里也祝各位哥哥姐姐早日到达自己的星辰大海
🎆1.浮点型在内存中的存储
上一章,我们介绍了整形家族和浮点型家族,以及整形在内存中的存储,整型的原码、反码、补码、大小端的认识,接下来,我们会介绍非常独特的浮点型在内存中的存储方式!
用一个例子为大家讲解:
🎇1.1例子
int main()
{
int n = 9;
float* pfloat = (float*)&n;
printf("n的值为:%d\n", n);
printf("*pfloat的值为:%f\n", *pfloat);
*pfloat = 9.0;
printf("n的值为:%d\n", n);
printf("pfloat的值为:%f\n", *pfloat);
return 0;
}
在存储的时候,我们将整型n转化成浮点型存放在浮点型的指针变量*pfloat中,当用%d去解读n的时,打印出了9,用%f去解读 pfloat时,却发现打印出了0。而将 *pfloat定义为小数9.0时,再用%d去解读,打印出来一串奇怪的数字,而用%f去解读存在 *pfloat中的小数时,却打印出了9.0.
所以,可以看出,浮点型和整型在内存中的存储以及分别去进行解读所得出的结果是不一样的!但是,num和float在内存中明明是同一个数,为什么浮点型和整数的 的解读结果会差别那么大呢?
🎇1.2浮点数的存储规则
下面先介绍一下理论概念
根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成以下形式。
- (-1) ^ S * M * 2 ^ E
- (-1)^S表示符号位,当S=0,V为正数;当S=1.V为负数
- M表示有效数字,1=<M<=2
- 2^E表示指数位
请看讲解:
但是,S M E 它们站内存的比例也是有所不同的。请看图讲解
但是,所占内存比例有了,最终他们分别是怎么存的呢?下面为大家讲解!
对于指数E,情况就比较复杂了
首先,E是一个无符号整数,这意味着,它的取值范围是0~255;如果E位11位,它的取值范围是0 ~ 2047.但是科学计数法是可以计算出来负数的(就像上面举的0.5的例子),所以IEE 754规定,存入内存时,E的真实值必须再加上一个中间数,对于8位的E,这个中间数时127;对于11位的E,这个中间数时1023.请看图讲解
具体大小端问题,可以查阅这篇文章《大小端的介绍》
对于指数E从内存中取出来还可以再分为三种情况:
E为全0或不为全1
即指数E的计算值减去127(或1023),即得到真实值,再将有效数字M前加上第一位的1.
比如:
5.5的二进制形式101.1,将小数点向右移动两位变成1.011,转化为科学计数法是1.011 * 2^2, E就是2+127=129.存储的时候用二进制表示就是10000001;M是01100000000000000000000;在取出的时候,E的值就减去127即得到真实值2,再将有效数字M前加上第一位的就得出1011
E为全0
当E为全0时,说明科学计数法中的E时-127,当E为-127时,2^-127是一个非常非常小的数,然后加上中间值127这时,E就变成了0,所以就规定,E为全0时,取出时就不再计算,直接变成了浮点数的指数E等于1-127即为真实值,有效数字不再加上第一位的1,二十还原成0.xxxxxx的小数,这样做说是为了表示±0,以及接近于0的很小的数字
E为全1时
这时如果有效数字为全0,表示正负无穷大。当E为全1时,值是255,说明E大概就是128的范围,128+127=255,所以1.xxxxx * 2^128是一个很大大数字,
下面,我们对都1.1的例子进行一下讲解