数据在内存中的存储
1.整数在内存中的存储
我们知道整数的表示方法有三种,即原码,反码,补码;
三种表示方法均有符号位和数值位两部分,其中符号位是用0表示正,用1表示负,符号位是数值的最高位,剩下的都是数值位。
正整数的原码,反码,补码相同;
负整数的三种表示方法表示规则各有不同:
- 原码:直接将数值按照正负数的形式换算成二进制得到的结果就是原码;
- 反码:将原码的符号位不变,其他位依次按位取反,得到的就是反码;
- 补码:在反码的基础上+1得到的就是补码;
对于整型来说:数据存放在内存中是以补码的形式存放的;
- 在计算机系统中,数值一律用补码来存放和表示
- 使用补码可以将符号位和数值位统一处理;
- 加法和减法也可以统一处理(CPU只有加法器)
- 补码和原码可以相互转换,运算过程相同,不需要额外的硬件电路;
2.浮点数在内存中的存储
在了解浮点数在内存中的存储前,我们需要先知道科学计数法的表示方法:
- 把一个数表示成
a
与10
的n
次幂相乘的形式(1≤|a|<10,a不为分数形式,n为整数),这种记数法叫做科学记数法
这是10进制的科学计数法的表示方式,但是但是我们研究的是二进制的浮点数的表示方法,所以与10
进制的科学计数法的区别是:权重的不同,10进制的权重是
1
0
n
10^n
10n,而二进制的权重是
2
n
2^n
2n。
比如:10.5
(十进制)的科学计数法是
1.05
∗
1
0
2
1.05*10^2
1.05∗102,那么10.5
转化成二进制是1010.1
,科学计数法表示是
1.0101
∗
2
3
1.0101*2^3
1.0101∗23.
我们常见的浮点数3.1415,1E10
(
1
∗
1
0
10
1*10^{10}
1∗1010)等,浮点数的类型有很多,如float
,double
,long double
类型。浮点数的表示范围在<float.h>
定义,我们可以在这个头文件里面找到浮点数定义的取值范围。所以我们整数的取值范围同样可以在<limit.h>
中找到;
2.1浮点数在计算机内部的表示方法
- 根据国际标准IEEE(电气电子工程师学会the Institute of Electrical and Electronics Engineers)754,任意一个二进制浮点数V都可以表示成下面的形式:
-
V = ( − 1 ) S (-1)^S (−1)S * M * 2 E 2^E 2E
- ( − 1 ) S (-1)^S (−1)S 表示符号位,当S = 0时,V是正数;当S = 1时,V为负数;( ( − 1 ) 1 (-1)^1 (−1)1等于1,所以为正; ( − 1 ) 1 (-1)^1 (−1)1次方还是-1,所以为负)
- M 表示有效数字,M的取值范围是[1,2);(根据二进制的科学计数法可得)
- 2 E 2^E 2E 表示指数位;(也就是二进制科学计数法的权重 2 n 2^n 2n)
-
例如:
- 十进制的
6.0
,写成二进制是110.0
,相当于 1.1 ∗ 2 2 1.1*2^2 1.1∗22;- 那么按照上面
V
的格式,就可以得出S = 0,M = 1.1,E = 2;
- 那么按照上面
- 十进制的
-6.0
,写成二进制是-110.0
,相当于 − 1.1 ∗ 2 2 -1.1*2^2 −1.1∗22;- 那么S = 1,M = 1.1,E = 2;
根据IEEE的规定:
-
对于32位的浮点数(float类型),最高的1位储存符号位S,接着后面的8位存储的是指数位E,剩下的23位储存的是有效数字M;
-
对于64位的浮点数(double类型),最高的1位储存的是符号位S,接着的11位存储的是指数E,剩下的52位存储的是有效数字M
2.2浮点数存的过程
-
IEEE 754对于有效数字M和E,还有一些特殊的规定:
- 刚刚我们提到M的取值范围是[1,2),也就是说M是写成1.xxxxx的形式,其中xxxxx表示的是小数部分;
- IEEE 754规定,在计算机内部保存M时,默认M的值的第一位始终是1,因此可以被省略舍去,只保存后面的xxxxx的部分。比如说,在保存1.001的时候,只保存001,等到读取的时候,在把第一位的1加上。这样做的目的是,节省1位有效数字的保存空间。例如以32位浮点数来说,留给M的只有23位,将第一位的1舍去后,就相当于可以保存24位M有效数字。
- 刚刚我们提到M的取值范围是[1,2),也就是说M是写成1.xxxxx的形式,其中xxxxx表示的是小数部分;
-
对于指数E来说:
E
是一个无符号整数(unsigned int)- 所以这就意味着,如果
E
是8
位,那么他的取值范围就是0 ~ 255;如果E是11位,那么他的取值范围就是0 ~ 2047; - 但是我们知道科学计数法的E是允许负数出现的(
2
E
2^E
2E中的E可以是负数,比如说十进制0.5的二进制是
0.1
,那么转化成科学计数法就是 1 ∗ 2 − 1 1*2^{-1} 1∗2−1,这时候E = -1
,是一个负数),所以IEEE 754规定,存入内存中的E的真实值必须加上一个中间数,对于8位的E,中间数是127
;对于11位的E,中间数是1023
.例如: 2 10 2^{10} 210的E = 10
,所以保存位32位浮点数时,必须保存成10 + 127 = 137
,即10001001;
- 所以这就意味着,如果
2.3浮点数取的过程
指数E从内存中取出来还有三种情况:
-
E不全为0或不全为1:
-
浮点数的指数E的计算值减去
127
(或1023),得到真实值,再将有效数字M第一位前加上1:- 例如:
0.5
的二进制是0.1
,由于规定正数的部分必须为1
,则将小数点向后移1
位,得到 1.0 ∗ 2 − 1 1.0*2^{-1} 1.0∗2−1,其中指数E= -1
,则-1 + 127(中间数) = 126
,二进制表示01111110
,而有效数字M = 1.0
,1.0
去掉整数部分得到0
,补齐二进制0
直到23
位为止,即0000000000000000000000
,所以0.5在内存中的存储表示方式为:
0 01111110 00000000000000000000000
- 例如:
-
-
E全为0:
- 语法规定:浮点数的指数
E = 1 - 127
(或这1 - 1023)即为真实值,有效数字M不再加上第一位的1
,而是还原为0.xxxxx
的小数。这样是为了表示±0,以及接近于0
的很小的数字。
- 语法规定:浮点数的指数
-
E全为1:
- 如果有效数字M全为0,表示±无穷大(正负取决于符号位S);