整数和浮点数在内存中的存储

整数:对于整数来说,在内存中以补码形式存储。

正数:(符号位(最高位的第一位当作符号位)为0)

原码,补码,反码都是相同的

负数:(符号位(最高位的第一位当作符号位)为1)

原码:将整数按照正负形式翻译成二进制

反码:原码符号为不变,其他位按位取反

补码:反码加一

浮点数:按照 V=(-1)^S * M * 2^E 来存储

(-1)^S * M * 2^E

(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。

M表示有效数字,大于等于1,小于2。

2^E表示指数位。

例如:十进制的 10.5,写成二进制是:1010.1,可看成 1.0101×2^3。

此时的 S=0;M=1.0101;E=3。

十进制的 -10.5,写成二进制是:-1010.1,可看成 -1.0101×2^3。

此时的 S=1;M=1.0101;E=3。

对于 32 位浮点数最高位 1 位存储 S ;接着 8 位存储 E ;最后 23 位存储 M。 

SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM

对于 64 位浮点数最高位 1 位存储 S ;接着 11 位存储 E ;最后 52 位存储 M。 

SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMM

M

MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
对于 M 的存储规则:

M 有效位的范围就在1~2之间。所以M可以写成 1.xxxxx的形式,在保存M时,默认只保存 1.xxxxx 中的xxxxx这一部分,这个1不保留。比如1.0101,只保留0101进计算机,这个1不保留。

综上:对于有效位M,只保留小数点后面的位数,不保留小数点前面的1。

对于 E 的存储规则:

当 E 为一个无符号整数(unsigned int)时

如果E为8位,它的取值范围为0~ 255;如果E为11位,它的取值范围为0~2047。由于科学计数法中的 E 是可以出现负数,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的 E ,这个中间数是127;对于11位的E,这个中间数是1023。

例如:2^6 的 E 是 6 ,所以保存成 32 位浮点数时,必须保存成6+127=133,即 10000101。

取出 E 时有三种情况:
1. E 不全为 0 ,不全为 1 时:

这时,浮点数就采用指数 E 的计算值减去127(或1023),得到真实值,再将有效数字 M 前加上第一位的1。

例如:0.5 的二进制形式为0.1,因为对于二进制来说,小数点后面的指数就是2^-1, 2^-2 , 2^-3 ,等等。由于规定正数部分必须为1,即将小数点右移1位,则为1.0*2^(-1),则 E 为 -1+127=126,表示为 01111110 ,而尾数 1.0 去掉整数部分为 0 ,补齐0到23位00000000000000000000000,则其二进制表示形式为:0 01111110 00000000000000000000000。

E 全为 0 时:

这时,浮点数的指数E等于 1-127(或者 1-1023)即为真实值,有效数字 M 不再加上第一位的 1,而是还原为 0.xxxxxx 的小数。这样做是为了表示 ±0,以及接近于 0 的很小的数字。例如:0 00000000 00000000000000000000000。

E 全为 1 时:

有效数字全为 M 全为 0 时,表示正负无穷大(正负由符号位 S 确定),例如:0 11111111 01000000000000000000000 表示正无穷;

1 11111111 01000000000000000000000 表示负无穷。

下面来分析一个代码:

#include<stdio.h>
int main()
{
int n = 11;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 11.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
return 0;
}

11 的原码是 00000000000000000000000000001011,整数的原码,反码,补码相同。

所以 11 补码是 00000000000000000000000000001011,

当存放到浮点型中时把最高位当成符号位 S ,接下来的八位当成指数 E ,后面的23位当成有效数字 M 。

故S =0,E = 1 - 127 = -126 ,由于 E 为全 0 的数,在全 0 中,M 读取出来时候不再补 1,而是补 0,

故M = 0.00000000000000000001011。即 (-1)^0 × 2^(-126) × 0.00000000000000000001011 相当于1成一个非常非常无限接近于0的数,所以结果无限接近于0,打印出来%f打印到小数点第六位,故打印结果为0.000000。

11.0 存放到浮点数里是 0 10000010 01100000000000000000000 。以 %d 形式打印出来,%d 会认为是的二进制序列是整型存储方式,转换成 10 进制时是:

所以打印出来的是:11,0.000000,1093664768,11.000000

再看下运行结果:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值