第三节 信息的表示和处理
一. 信息存储
1、 字节
最小的可寻址的存储器单位,每个字节由唯一的数字来标识,称为地址。
2、 进制的表示和转化
① 十进制转二进制方法为:十进制数除2取余法,即十进制数除2,余数为权位上的数,得到的商值继续除2,依此步骤继续向下运算直到商为0为止。
② 二进制转十进制方法为:把二进制数按权展开、相加即得十进制数。
③ 二进制转八进制方法为:3位二进制数按权展开相加得到1位八进制数。(注意事项,3位二进制转成八进制是从右到左开始转换,不足时补0)。
④ 八进制转成二进制方法为:八进制数通过除2取余法,得到二进制数,对每个八进制为3个二进制,不足时在最左边补零。
⑤ 二进制转十六进制
⑥ 方法为:与二进制转八进制方法近似,八进制是取三合一,十六进制是取四合一。(注意事项,4位二进制转成十六进制是从右到左开始转换,不足时补0)。
⑦ 十六进制转二进制
⑧ 方法为:十六进制数通过除2取余法,得到二进制数,对每个十六进制为4个二进制,不足时在最左边补零。
⑨ 把十进制转八进制或者十六进制按照除8或者16取余,直到商为0为止。
3、 布尔代数
布尔代数起源于数学领域,是一个用于集合运算和逻辑运算的公式:〈B,∨,∧,¬ 〉。其中B为一个非空集合,∨,∧为定义在B上的两个二元运算,¬为定义在B上的一个一元运算。
通过布尔代数进行集合运算可以获取到不同集合之间的交集、并集或补集,进行逻辑运算可以对不同集合进行与、或、非。
基本规则:
1.a+b=b+a, a·b=b·a.
2.a·(b+c)=a·b+a·c,
a+(b·c)=(a+b)·(a+c).
3.a+0=a, a·1=a.
4.a+a′=1, a·a′=0.
4.补码
最常见的有符号数的计算机表示方式。
正数的补码=原码
负数的补码=原码各位取反再加1
最高有效位也叫符号位。
5、 寻址和字节顺序
小端法:最低有效字节在最前面,“高对高,低对低”,是大多数intel兼容机,包括IBM和Sun的个人intel兼容处理器的计算机使用的规则。
例如:变量x为int,位于地址0x100,十六进制值为0x01234567。
大端法:地址: 0x100 0x101 0x102 0x103
67 45 23 01
在0x01234567中,高位字节为0x01,低位字节为0x67。
二、整数表示
1、有符号数和无符号数之间的转换
对大多数C语言实现而言,处理同样字长的有符号数和无符号数之间相互转换的一般规则是:
数值可能会改变,但是位模式不变。
一个有符号数x和与之对应的无符号数T2Uw(x)之间的关系:
T2Uw(x)= x+2^w , x<0
x , x>=0
2.扩展数字的位表示
零扩展:在开头添0。(将无符号数转换成更大的数据类型)
符号扩展:添加最高有效位的值的副本。(一个补码数字转换成更大的数据类型)
3.截断数字
可能会改变数值——溢出的一种形式。
对于无符号数字x,截断到k位,相当于计算:x mod 2(k)。(k次幂)
4.C语言中的有符号数和无符号数
当C语言执行一个运算,若一个运算数有符号而另一个运算数无符号,C语言会隐式地将有符号强转为无符号,并假设两者都非负,执行运算。
PS:要想让负数等于正数,可以让这个负数和这个正数的无符号形式相等,再在对比时将两者之一强转为无符号形式,即可。
5.扩展一个数字的位表示
一个常见的运算是在不同字长的整数之间转换,同时又保持数值不变。当然,当目标数据类型太小了,以至于不能表示想要的值时,这可能根本就是不可能的。然而,从一个较小的数据类型转换到一个较大的类型,应该总是可能的。要将一个无符号数转换为一个更大的数据类型,我们只要简单的在表示的开头添加0.这种运算被称为零扩展(zero extension)。要将一个二进制补码数字转换为一个更大的数据类型,规则是执行一个符号扩展(sign extension),在表示中添加最高有效位的值。
三、整数运算
1、补码加法
补码加法
[X+Y]补 = [X]补 + [Y]补
注:因为计算机中运算器的位长是固定的(定长运算),上述运算中产生的最高位进位将丢掉,所以结果不是100001010,而是00001010。
2、补码减法
[X-Y]补 = [X]补 - [Y]补 = [X]补 + [-Y]补【1】
3、补码乘法
补码的乘法不具备【X*Y】补=【X】补×【Y】补的性质。但是【X*Y】补==【X】补×Y,所得结果再取补码,如x=101,y=011,[x*y]补=-[(-101)*011]=-[011*011]=-01001=10111
4、乘以常数
在机器运算中,乘法总是很慢的,而加法和移位(左移)是相对较快的。所以在编译器中,会使用移位和加法运算组合的方式来代替乘以常数因子。这种方法对于无符号运算和补码运算都是适用的。
常数为2的k次幂的时候直接左移k位即可。
常数不是2的整数次幂的时候将常数C表示为2的几个整数次幂的和,结合移位运算和加法运算。
5、除以2的幂
机器运算中,除法比乘法更慢。当被除数为2的整数次幂时,通过右移来解决。右移时需要区分无符号数和补码。
四、浮点数
1.二进制小数
定点表示法:“.”为界(不能有效的表示很大的数)
十进制:小数点左边的数字的权是10的非负幂,得到整数值;右边的数字的权是10的负幂,得到小数值。
二进制:小数点左边的数字的权是2的非负幂,右边的数字的权是2的负幂。
2.IEEE浮点表示
用V = (-1)s * M * 2E的形式来表示一个数:
符号:s决定这个数是负数(s = 1)还是正数(s = 0),而对于数值0的符号位解释作为特殊情况处理。
尾数:M是一个二进制小数,它的范围是1 ~ 2-ε,或者是0 ~ 1-ε。
阶码:E的作用是对浮点数据加权,这个权重是2的E次幂(可能是负数)。将浮点数的位表示划分为三个字段,分别对这些值进行编码:
一个单独的符号位s直接编码符号s。
k位的阶码字段exp = ek-1…e1e0编码阶码E。
n位小数字段frac = fn-1…f1f0编码尾数M,但是编码出来的值也依赖于阶码字段的值是否等于0。
3.两种常见的格式
C语言中的单精度浮点格式float 和双精度浮点格式double。
在float中,s、exp和frac字段分别为1位、k = 8 位和n = 23位,得到一个32位的表示;
在double中,s、exp和frac字段分别为1位、k = 11 位和n = 52位,得到一个64位的表示。
遇到问题与解决
为什么会产生负溢出
解答:通过百度和参考书上的例题知道,和正溢出一样,只要超过了这个数据的字节数,则会溢出,只是正溢出是正值,负溢出是负值超出了下限。