第二章要解决的问题如下:
1.8位的计算机定点整数表示,范围是多大?讨论原、反、补码的情况。
2.半加器和全加器的电路?
3.行波进位加法器的缺点,以及延迟分析(以8位为例)?
4.8位并行加法器设计电路
5.定点数表示数和浮点数表示的区别和联系?IEEE754为什么阶码部分为什么采用移码表示?
6.为什么要校验位?奇偶校验码的作用?
7.海明码和CRC码的编码方法,以及各自用途。
8.国标码GB2312汉字编码和存储规则。
9.如何判断溢出,以及溢出电路设计?
10.logisim和verilog两种软件如何使用,以及他们的用途是什么?
11.为什么减法可以通过加法实现?
12.移位运算是什么?
知识储备
1.原码、反码、补码
1.真值与机器数
为了区分一般书写的数和机器中的编码数,我们有如下定义:
真值:
一般书写表示的数
机器数(或机器码):
机器中用编码表示的数
机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0
、负数为1
。
比如,十进制中的数+3
,如果计算机字长为8
位,转换成二进制就是00000011
。如果是-3
,就是10000011
。这里的 00000011
和10000011
就是机器数。
因为第一位是符号位,所以机器数的值不等于真正的数值。例如上面的有符号数10000011
,其最高位1代表负,其真正数值是 -3
,而不是131
。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。
例:00000001
的真值 = +0000001
= +1
,10000001
的真值 = –0000001
= –1
2.原码
1.原码的定义
原码是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0
,负数该位为1
,其余位表示数值的大小。
[
x
]
原
=
{
x
0
≤
x
<
2
n
2
n
−
x
=
2
n
+
∣
x
∣
−
2
n
<
x
<
0
[x]_原= \begin{cases} x& \text{$0\le x<2^n$ }\\ 2^n-x=2^n+|x|& \text{$-2^n<x<0$} \end{cases}
[x]原={x2n−x=2n+∣x∣0≤x<2n −2n<x<0
当
x
<
0
x<0
x<0时,
[
x
]
原
[x]_原
[x]原相当于在
x
x
x的最前位加了个1。
举个例子,当
x
=
+
1011
x=+1011
x=+1011时,
[
x
]
原
=
01011
[x]_原=01011
[x]原=01011;当
x
=
−
1011
x=-1011
x=−1011时,
[
x
]
原
=
2
4
−
(
−
1011
)
=
2
4
+
1011
=
11011
[x]_原=2^4-(-1011)=2^4+1011=11011
[x]原=24−(−1011)=24+1011=11011
其中
[
x
]
原
[x]_原
[x]原是机器数
,
x
x
x是真值
。
2.原码的优点
简单直观;例如,我们用8
位二进制表示一个数,+11
的原码为00001011
,-11
的原码就是10001011
3.原码的缺点
0
的表示不唯一,有+0
和-0
之分。而且原码的加法运算复杂。这是因为,当两数相加时,如果是同号则数值相加;如果是异号,则要进行减法。而在进行减法时,还要比较绝对值的大小,然后大数减去小数,最后还要给结果选择恰当的符号。
2.反码
1.反码的定义
反码是在原码的基础上,符号位不变而数值位按位取反。
[
x
]
反
=
{
x
0
≤
x
<
2
n
2
n
+
1
+
x
−
1
−
2
n
<
x
<
0
[x]_反= \begin{cases} x& \text{$0\le x<2^n$ }\\ 2^{n+1}+x-1& \text{$-2^n<x<0$} \end{cases}
[x]反={x2n+1+x−10≤x<2n −2n<x<0
其中
x
<
0
x<0
x<0时,
[
x
]
原
+
[
x
]
反
=
2
n
+
1
+
2
n
−
1
[x]_原+[x]_反=2^{n+1}+2^n-1
[x]原+[x]反=2n+1+2n−1,从而推出
[
x
]
反
[x]_反
[x]反的表达式
举个例子:当
x
=
−
1011
x=-1011
x=−1011时,
[
x
]
原
=
2
4
−
(
−
1011
)
=
2
4
+
1011
=
11011
[x]_原=2^4-(-1011)=2^4+1011=11011
[x]原=24−(−1011)=24+1011=11011,而
[
x
]
反
=
10100
[x]_反=10100
[x]反=10100,
[
x
]
原
+
[
x
]
反
=
101111
=
2
5
+
2
4
−
1
[x]_原+[x]_反=101111=2^5+2^4-1
[x]原+[x]反=101111=25+24−1
2.反码的优点
运算相对原码简单,符号位参与运算,只需要设置加法器,但符号位进位位需要加到最低位。
3.反码的缺点
反码的表示相对原码比较复杂,而且0的表示也不唯一。
3.补码
1.补码的定义
补码的表示是在反码的基础上再加1。
[
x
]
补
=
{
x
0
≤
x
<
2
n
2
n
+
1
+
x
−
2
n
≤
x
≤
0
[x]_补= \begin{cases} x& \text{$0\le x<2^n$ }\\ 2^{n+1}+x& \text{$-2^n\le x\le0$} \end{cases}
[x]补={x2n+1+x0≤x<2n −2n≤x≤0
其中
x
<
0
x<0
x<0时,
[
x
]
补
=
[
x
]
反
+
1
[x]_补=[x]_反+1
[x]补=[x]反+1,从而推出
[
x
]
补
[x]_补
[x]补的表达式
2.补码的优点
补码的运算简单,只需要设置加法器,而且0
的表示唯一。
3.补码的缺点
补码的表示相对原码比较复杂。
4.移码
移码一般在阶码中采用,由移码定义可知,移码无负值。且相同位数的补码与移码表示范围相同。
5.编码方式
对于一个数,计算机要使用一定的编码方式进行存储,原码、反码、补码是机器存储一个具体数字的编码方式。
原码的表示方法是:
符号位加上真值的绝对值,即用第一位表示符号,其余位表示值。
反码的表示方法是:
正数的反码就是其本身;负数的反码是在其原码的基础上,符号位不变,其余各位取反。
补码的表示方法是:
正数的补码就是其本身;负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1,即取反+1。
6.为什么采用原码、反码和补码
首先,让我们看一个最简单的加法,-1
与1
相加。
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
如果用原码表示, 让符号位也参与计算,显然对于减法来说结果是不正确的。比如上面计算得到的就是-2
这也就是为何计算机内部不使用原码表示一个数。
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原= [00000001]反 + [11111110]反 = [11111111]反 = [10000000]原 = -0
为了解决原码做减法的问题,人们发明了反码,但是人们又发现用反码计算减法,结果的真值部分是正确的,而唯一的问题出现在0
这个特殊的数值上。虽然人们理解上+0
和-0
是一样的,但是0
带符号是没有任何意义的。
1-1 = 1 + (-1) = [00000001]原 + [10000001]原 = [00000001]补 + [11111111]补 = [00000000]补=[00000000]原 = 0
最后补码出现了,它解决了0
的符号以及两个编码的问题。除此之外,我们还可以用[10000000]补
表示-128
,但是-128
没有原码和反码表示。
(-1) + (-127) = [10000001]原 + [11111111]原 = [11111111]补 + [10000001]补 = [10000000]补
所以,使用补码不仅仅修复了0
的符号以及存在两个编码的问题,而且还能够多表示一个最低数,这就是为什么8位二进制使用原码或反码表示的范围为 [-127, +127]
,而使用补码表示的范围为 [-128, 127]
的原因。而在补码
2.半加器与全加器
半加器
如果仅仅考虑两个1位二进制数A和B相加,而不考虑低位的进位,称为半加。实现半加运算的电路叫做半加器。半加器有两个输入端A和B,两个输出端S和C,其中S为和,C为向高位的进位。
半加器的真值表如下:
A | B | Carry | Sum |
---|---|---|---|
0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 |
1 | 0 | 0 | 1 |
1 | 1 | 1 | 0 |
由真值表可以写出逻辑表达式:
S
=
A
⊕
B
S=A\oplus B
S=A⊕B
C
=
A
B
C=AB
C=AB
显然,我们可以用异或门和与门实现S和C从而构成半加器。
全加器
为了说明什么是全加,我们首先要知道什么是半加,由上述知识可知,半加就是在两个二进制数进行相加时,不考虑低位向高位的进位,而全加就是考虑了低位向高位的进位,这样才能反映两个二进制数相加过程中任何一位相加的一般情况。实现全加的电路就叫全加器。
全加器真值表如下:
A | B | Cin | Cout | Sum |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 0 | 1 |
0 | 1 | 0 | 0 | 1 |
0 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 0 | 1 |
1 | 0 | 1 | 1 | 0 |
1 | 1 | 0 | 1 | 0 |
1 | 1 | 1 | 1 | 1 |
由真值表我们可以写出输出逻辑表达式:
S
=
(
A
⊕
B
)
⊕
C
i
n
S=(A\oplus B)\oplus Cin
S=(A⊕B)⊕Cin
C
o
u
t
=
(
A
⊕
B
)
C
i
n
+
A
B
Cout=(A\oplus B)Cin+AB
Cout=(A⊕B)Cin+AB
由此可见,
S
S
S是半加和
A
⊕
B
A\oplus B
A⊕B与低位进位
C
i
n
Cin
Cin的异或逻辑,因此可以用两个半加器和一个或门组成一个全加器。
3.行波进位加法器
1.行波进位加法器的定义
N-bit
加法器可以根据1-bit
全加器组合而成。每个全加器的输出进位cout
作为下一个全加器的输入进位cin
,这种加法器称为行波进位加法器(Ripple-carry adder,简称RCA)。
行波进位是指进位信号从低位逐位向高位传递,特点是结构简单,但是由于后一位的进位依赖于前一位的进位,所以关键路径更长,限制速度,性能不高。
2.行波进位加法器的时延分析
例如下面一个4bit
行波进位加法器的时延分析
如上图所示,假设一个基本门电路时延为T
,与非,或非为2T
,异或为3T
,则该四位加法器的时延为最长路线的时延之和,例如上图的时延为3T+T+T+T+T+T+T+T+T=3T+2T*4=11T
,由此我们也可推出8bit
行波进位加法器时延为3T+2T*8=19T
。但是这种是建立在我们假设了时延大小的情况下计算得出的,具体的时延还要根据题目具体分析。
4.8位并行加法器
5.定点数与浮点数
1.定点数
所谓定点
,即约定机器中所有数据的小数点位置是固定不变的,因此既可以表示整数,也可以表示小数。原理上讲,小数点位置固定在哪一位都可以,但是我们通常将数据表示成纯小数
或纯整数
。
假设用一个
n
+
1
n+1
n+1位字来表示一个定点数
x
x
x,其中一位
x
n
x_n
xn用来表示数的符号,其余位数表示它的量值,这样,对于任意的定点数
x
x
x,我们可以在定点机中表示为如下形式:
如果数
x
x
x表示的是纯小数
,那么小数点位于
x
n
x_n
xn和
x
n
−
1
x_{n-1}
xn−1之间,且数的绝对值表示范围为:
0
≤
∣
x
∣
≤
1
−
2
−
n
0\le |x|\le1-2^{-n}
0≤∣x∣≤1−2−n
如果数
x
x
x表示的是纯整数
,那么小数点位于最低位
x
0
x_0
x0的右边,且数的绝对值表示范围为:
0
≤
∣
x
∣
≤
2
n
−
1
0\le |x|\le2^n-1
0≤∣x∣≤2n−1
2.浮点数
所谓浮点
,即把数的范围和精度分别表示,相当于数的小数点位置随比例因子的不同而在一定范围内可以自由浮动。
在计算机中一个任意二进制数
N
N
N可以写成:
N
=
2
e
⋅
M
N=2^e\cdot M
N=2e⋅M
其中
M
M
M称为浮点数的尾数,是一个纯小数。
e
e
e是比例因子的指数,称为浮点数的指数,常称阶码,是一个整数。
在机器中表示一个浮点数时,一是要给出尾数,用定点小数形式表示。尾数部分给出了有效数字的位数,因而决定了浮点数的表示精度。二是要给出指数,用整数形式表示,阶码(指数)指明小数点在数据中的位置,因而决定了浮点数的表示范围。
阶码:-01=101
,对应补码为111
;
尾数:-0.1110=11110
,对应补码为10010
;
最后结果为11110010
。
3.IEEE754标准
早期,各个计算机系统的浮点数使用不同的机器码表示阶和尾数,给数据的交换和比较带来很大麻烦,因此现在的计算机都采用统一的IEEE754
标准的格式表示浮点数,其中规定了32位短浮点数
和64位长浮点数
的标准格式为:
其中,
S
S
S是浮点数的符号位,
S
=
0
S=0
S=0表示正数,
S
=
1
S=1
S=1表示负数;
M
M
M是尾数,占用23位,小数点位置放在尾数域最高有效位的右边;
E
E
E是阶码,占用8位,阶符采用隐含方式,即采用移码来表示正负指数。用这种方式时,将浮点数的指数真值
e
e
e变成阶码
E
E
E时,应将指数加上一个固定的偏置数127
,即
E
=
e
+
127
E=e+127
E=e+127。
浮点数的规格化表示
不论是32位浮点数
还是64位浮点数
,如果不对浮点数的表示作出明确规定,同一个浮点数的表示就不是唯一的。例如
(
1.75
)
10
(1.75)_{10}
(1.75)10可以表示成
1.11
×
2
0
、
0.111
×
2
1
、
0.0111
×
2
2
1.11\times2^0、0.111\times2^1、0.0111\times2^2
1.11×20、0.111×21、0.0111×22等多种形式。为了提高数据的表示精度,当尾数的值不为0
时,尾数域的最高有效位应为1
,这就是浮点数的规格化表示。
一个规格化的32位浮点数
x
x
x的真值表示为:
x
=
(
−
1
)
S
×
(
1.
M
)
×
2
E
−
127
,
e
=
E
−
127
x=(-1)^S\times(1.M)\times2^{E-127},e=E-127
x=(−1)S×(1.M)×2E−127,e=E−127
一个规格化的64位浮点数
x
x
x的真值表示为:
x
=
(
−
1
)
S
×
(
1.
M
)
×
2
E
−
1023
,
e
=
E
−
1023
x=(-1)^S\times(1.M)\times2^{E-1023},e=E-1023
x=(−1)S×(1.M)×2E−1023,e=E−1023
对于32位浮点数
N
N
N,IEEE754
定义:
4.定点数与浮点数的区别和联系
1.当相同位数的计算机表示数据(比如64位),浮点数能表示的数据范围远远大于定点数表示的数据范围。
2.当相同位数的计算机表示数据(比如64位),浮点数的相对精度比定点数要高。
3.浮点数在计算时,要分阶码部分的计算和尾数部分的计算,而且运算结果要求规格化,故浮点运算步骤比定点数运算步骤多,运算速度比定点运算速度低。
5.阶码部分为什么用移码表示
这是为了方便浮点数在进行加减运算时进行对阶操作,也就是比较大小。
比如
(
1.01
×
2
−
1
)
+
(
1.11
×
2
3
)
(1.01\times 2^{-1})+(1.11\times2^3)
(1.01×2−1)+(1.11×23)这两个数相加 ,在科学计数法中,通常是将小阶向大阶看齐。也就是将
2
−
1
2^{-1}
2−1变为
2
3
2^3
23。
如果用补码来表示
−
1
-1
−1和
3
3
3,
−
1
:
111
,
3
:
011
-1:111,3:011
−1:111,3:011;很明显二进制中
111
111
111比
011
011
011大。所以结果会是第一个数大于第二个数,这是明显不对的。
因此通常是在阶的基础上加上偏置常数,当偏置常数为4时,-1+4=3;3+4=7;所以结果会是第二个数大于第一个数,这样才正确。
那为什么浮点型用
2
n
−
1
−
1
2^{n-1}-1
2n−1−1而不是
2
n
−
1
2^{n-1}
2n−1来作为偏移值呢,比如8位机器数采用127而不是128作为偏移值?
原因是127作为偏移值时表示的范围更大,例如阶码11111110以127作为偏移值转化为真值为127,而以128作为偏移值转化为真值为126,可以看出偏移值为127时,真值大一些,也就是可表示范围会大一点。
6.数据的校验
数据在计算机系统内被处理、传输和存储的过程中可能出现错误。为了减少和避免这类错误,引入了数据校验码。校验码的基本原理就是通过增加校验位提高码距,从而使编码具有检错或纠错能力。通常是在每个字上添加一些校验位,用来确定字中出现错误的位置。
码距的计算有两种方法:
例如对于0100
和1111
1.直接观察法:可以看出,两者有3
个数位的值不同,因此码距为3
。
2.异或计算法:0100
⊕
\oplus
⊕1111
=1011
,结果为1011
,里面有三个1
,结果里面有几个1
就代表有多少个数位值不同,即码距为3
。
码距越大,反映了码集中每两个码字之间的差别程度越大。那么从一个编码传输错误变成另一个编码的可能性越小。则其检错、纠错能力也就越强。
比如我们用0
代表女,1
代表男,(码距为1)这时候如果0
在传输的过程中变成了1
,那么我们没有办法判断是否发生了错误,因为1
仍然是一个正确的编码。
但比如我们用00
代表女,11
代表男,(码距为2)那么我们就可以检测出1位发生错误的情况,比如00
变成了10
或者01
,因为合法的编码只有00
和11
。
如果继续冗余,用000
代表女,111
代表男,(码距为3)同理。那么这时候我们可以检测出1位
和2位
发生错误的情况。同时,我们可以纠正1位
发生错误的情况,比如如果出现了001
,我们很清楚的知道它原来传输的正确编码应该是000
,因为只有1位
出错,所以不可能是111
变过来的。
码距越大,抗干扰能力越强,纠错能力越强,数据冗余越大,编码效率越低,编码电路也相对复杂,因此我们在选择码距时必须考虑信息发生差错的概率和系统能容许的最小差错率。
1.奇偶校验
基本原理:在原编码中增加一个校验位,则原编码就变成了校验码。
特点:奇偶校验码的码距为2,只能检测出奇数位出错,如果发生偶数位错误就无法检测,但经研究是奇数位发生错误的概率大很多, 而且奇偶校验码无法检测出哪位出错,所以属于无法纠正错误的校验码,并且无错结论不可信。
奇偶校验码是奇校验码和偶校验码的统称,它们都是通过在要校验的编码上加一位校验位组成。
奇校验
:加上校验位后,编码中1
的个数为奇数个。
偶校验
:加上校验位后,编码中1
的个数为偶数个。
为什么码距是2:
举个例子,给定被校验数据长度为6
,我们进行奇校验,则校验码可为1100010
,也可为1101011
,也就是只要保证校验码中1
的个数为奇数即可,而要想保持1
的个数为奇数,至少需要改变两位的值,因此码距为2
,偶校验同理。
2.CRC校验
CRC(Cyclic Redundancy Check)循环冗余校验码
基本原理:数据发送、接受方约定一个除数,
k
k
k个信息位
+
r
+r
+r个校验位作为被除数,添加校验位后要保证模2
除法的余数为0
,收到数据后,进行除法检查余数是否为0
,若余数非0
说明出错,则进行重传或纠错。
这里介绍一下多项式及其对应的编码。
可以看出,多项式与编码是一一对应的,即编码为多项式的系数值,而且多项式
G
(
X
)
G(X)
G(X)一般题目中会给出,直接利用即可。
校验位 r r r的位数是由生成多项式 G ( X ) G(X) G(X)的位数决定的,且是生成多项式的位数减一。
若余数位过少,我们就在前面补上0,保证余数位数比除数少一位即可。
若只考虑发生一位错误的情况下:应满足 k + r + 1 ≤ 2 r k+r+1\le2^r k+r+1≤2r, k k k为信息位, r r r为校验位。
循环特性:
前提:在一位出错情况下余数具有循环特性
方法:若余数不为0
,我们对余数右边补0
继续做模2
运算,同时得到的结果即为校验码左移一位出错的余数,如此循环,即可得到所有位单独出错的余数。
特点:接收端进行校验得到的余数与出错位位置和
G
(
X
)
G(X)
G(X)的取值有关,与
k
k
k位信息的取值无关。
例子:
对于被除数1100010
,除数为1011
,从左到右依次分为1、2...、7
,第5
位出错时,余数为100
,补0
继续模2
运算,得到余数为011
,也是第4
位出错时的余数。
下图可以用来练个手
3.海明校验
基本原理:将信息位分组进行偶校验,分成
r
r
r个校验位,
r
r
r个校验位标注出错位置。
校验位的写法是对应序号的校验位:
其中
P
1
P_1
P1校验位对应的数据位是含有
P
1
P_1
P1编号的,即含有
1
1
1,观察得
b
1
,
b
2
,
b
4
,
b
5
.
b
7
b_1,b_2,b_4,b_5.b_7
b1,b2,b4,b5.b7均含有
1
1
1,同理
P
2
P_2
P2校验位对应的数据位是含有
P
2
P_2
P2编号的,即含有
2
2
2,观察得
b
1
,
b
3
,
b
4
,
b
6
.
b
7
b_1,b_3,b_4,b_6.b_7
b1,b3,b4,b6.b7均含有
2
2
2,
P
3
P_3
P3校验位对应的数据位是含有
P
3
P_3
P3编号的,即含有
4
4
4,观察得
b
2
,
b
3
,
b
4
b_2,b_3,b_4
b2,b3,b4均含有
4
4
4,
P
4
P_4
P4校验位对应的数据位是含有
P
4
P_4
P4编号的,即含有
8
8
8,观察得
b
5
,
b
6
.
b
7
b_5,b_6.b_7
b5,b6.b7均含有
8
8
8。
故有
P
1
=
b
1
⊕
b
2
⊕
b
4
⊕
b
5
⊕
b
7
P_1=b_1\oplus b_2\oplus b_4\oplus b_5\oplus b_7
P1=b1⊕b2⊕b4⊕b5⊕b7,
P
2
=
b
1
⊕
b
3
⊕
b
4
⊕
b
6
⊕
b
7
P_2=b_1\oplus b_3\oplus b_4\oplus b_6\oplus b_7
P2=b1⊕b3⊕b4⊕b6⊕b7,
P
3
=
b
2
⊕
b
3
⊕
b
4
P_3=b_2\oplus b_3\oplus b_4
P3=b2⊕b3⊕b4,
P
1
=
b
5
⊕
b
6
⊕
b
7
P_1= b_5\oplus b_6\oplus b_7
P1=b5⊕b6⊕b7。
指错字的写法是对应序号的校验位加上校验位对应的数据位:
G
1
=
P
1
⊕
b
1
⊕
b
2
⊕
b
4
⊕
b
5
⊕
b
7
G_1=P_1\oplus b_1\oplus b_2 \oplus b_4\oplus b_5\oplus b_7
G1=P1⊕b1⊕b2⊕b4⊕b5⊕b7
G
2
=
P
2
⊕
b
1
⊕
b
3
⊕
b
4
⊕
b
6
⊕
b
7
G_2=P_2\oplus b_1\oplus b_3 \oplus b_4\oplus b_6\oplus b_7
G2=P2⊕b1⊕b3⊕b4⊕b6⊕b7
G
3
=
P
3
⊕
b
2
⊕
b
3
⊕
b
4
G_3=P_3\oplus b_2 \oplus b_3\oplus b_4
G3=P3⊕b2⊕b3⊕b4
G
4
=
P
4
⊕
b
5
⊕
b
6
⊕
b
7
G_4=P_4\oplus b_5\oplus b_6\oplus b_7
G4=P4⊕b5⊕b6⊕b7
7.溢出
在运算过程中,如果出现结果大于字长绝对值的现象,称为溢出。两个正数相加,结果大于机器字长所能表示的最大正数,称为正溢(上溢);两个负数相加,结果小于机器所能表示的最小负数,称为负溢(下溢)。
溢出只可能发生在同符号数相加时,例如对于两个正数相加,可能发生溢出,一正一负相加,不会发生溢出,两个负数相加,可能发生溢出。而对于减法,我们通过采用补码将其转换为了加法,一正减一负为两个正数相加,一正减一正为一正一负相加,一负减一正为两个负数相加,一负减一负为一负一正相加。
因而我们有以下的溢出判断方法:
原理:
V
=
1
V=1
V=1的成立条件是两个逻辑表达式的任意一个为真即可,也就是
X
0
X_0
X0和
Y
0
Y_0
Y0符号相同时,且与
S
0
S_0
S0的符号相反时。也就是两个正数相加为负或两个负数相加为正时
V
=
1
V=1
V=1。
原理:
V
=
1
V=1
V=1时发生溢出,即
C
0
C_0
C0与
C
1
C_1
C1不同,也就是数据位
C
0
C_0
C0进位时,符号位
C
1
C_1
C1并没有进位,而数据位
C
0
C_0
C0没有进位时,符号位
C
1
C_1
C1却进位了。
原理:
在数据位前面加上两位
00
00
00或
11
11
11,其中
00
00
00代表正数,
11
11
11代表负数,若两数相加得到
01
01
01,表明发生了正溢出,得到
10
10
10,表明发生了负溢出。
8.国标码GB2312
GB2312
将代码表分为94个区,对应第一字节;每个区94个位,对应第二字节,两个字节的值分别为区号值和位号值加32(20H)。01-09区
为符号、数字区,16-87区
为汉字区,10-15区
、88-94区
是有待进一步标准化的空白区。GB2312
将收录的汉字分成两级:第一级是常用汉字计3755个,置于16-55区
,按汉语拼音字母/笔形顺序排列;第二级汉字是次常用汉字计3008个,置于56-87区
,按部首/笔画顺序排列。故而GB2312
最多能表示6763个汉字。
因为
y
y
y是03区的第8行第9列,所以
y
y
y的码区就为
0389
0389
0389
同理,饼位于17区第9行第3列,故其码区为
1793
1793
1793
侃字位于57区第0行第9列,故其码区为
5709
5709
5709
最终字符的存储是将码区按前两位和后两位分开,并且将其转换为十六进制,然后分别加上
A
0
A0
A0,再将其合并。
为什么要加
A
0
A0
A0?
GB2312 是双字节编码,为了与 ASCII 码区分开,字节的第8位必须是1,所以GB2312是8位编码。所以至少要从 0x80(128, 1000 0000) 开始吧,但是根据上面的规定,0x80 - 0x9f 要留给控制块,所以只能从 0xA0 开始咯。那为什么 GB2312 编码不是从 0xA0 开始,而是 0xA1 开始呢? 因为 0xA0 正好是图形块的空格,所以就从 0xA1 编码,这就是 0xA0 的由来。
11.如何将减法转为加法
介绍这节内容时,我们先来彻底了解一下补码的意义。
如图所示,现在的时间是10
点,我想把时间调到7
点,那么我该怎么做呢?
第一种方法:将时针顺时针调9
个单位
第二种方法:将时针逆时针调3
个单位
无论我们采用哪个方法,最后得到的结果都是一样的,但是其中的数学思想却有极大的差别,因为第一种方法是加
,第二种方法是减
,但是两者却能做到殊途同归,这是为什么呢?
其实细想一下不难发现,这里用到了同余的知识,什么是同余呢?简单的说,就是模后的值相同。即9/12=9
,-3/12=9
。由此我们可以得到启发,减
跟加
得到的结果是一样的,那我们可不可以用加
来替代减
呢?
下面讲下模运算
怎么判断两个数同余呢?如果a的绝对值+b的绝对值=c*模,c为正整数
,则a,b同余
。
最后我们回到计算机里来,对于一个8bit
的二进制数而言,其模的值为
2
7
−
1
2^7-1
27−1,因此我们在进行加减运算时,可以考虑用补码来进行,补码是在反码的基础上末位+1
,而反码是在原码的基础上符号位不变,其余各位按位取反(这里考虑的是负数的机器码表示),因此补码+原码=模
,也就是二者同余,故可以得到相同的结果。也就是-原码=+补码
。这也解释了补码的定义为何是反码末位+1
。
如上图所示,对于无符号数,我们直接相加对结果没有影响,但是有符号就不一样了,如果是两个正数相加可以直接进行,但是一正一负就不行了,因为不清楚结果的符号是正还是负,如果变成减法又要设置减法器,这又会额外增加计算机的成本,于是我们就直接采用补码进行计算,这样正数相加没有影响,而负数的话又转为同余的正数,因此直接相加也没有影响,最后我们就实现了只用加法器就能进行加减运算。
12.移位
移位分为三种类型,算术移位、逻辑移位与循环移位。
1.算术移位
对于算术移位,因为我们要考虑数字的符号,所以符号位是不移动的,移动的是数值位。而算术移位又分为三种情况:原码、反码及补码。
1.原码的算术移位
如上图所示,为定点小数的算术移位,对于定点整数也是同样的操作。
2.反码的算术移位
对于正数的反码,移位运算与原码相同;对于负数的反码,因为反码的数值位与原码相反,因此原来原码进行补位时补的0
变成反码就应该补1
。
3.补码的算术移位
对于正数的补码,移位运算与原码相同;对于负数的补码,
最后对三种情况进行总结,如下图所示,但要注意的是,由于计算机的位数有限,因此有时候无法用算数移位精确地等效乘除法。
2.逻辑移位
如上图所示,逻辑移位比较简单,可以看做是无符号数的算术移位,因此就不需要考虑原码、反码和补码之类的。
3.循环移位
如上图所示,循环移位是指循环移动,用溢出位去补最低位或最高位。
举个例子:对于01101011
,进行循环左移一位后为11010110
,这个结果是怎么得到的呢?我们首先把所有位往左移,这时第一位的0
就相当于溢出,而第八位的0
又移到第七位,导致了此时的第八位为空,因此我们把溢出的0
放在第八位,这样就得到了循环左移一位的结果。循环右移也是同样的道理,比如对于01101011
,得到的结果为10110101
。
上面讨论的是不带进位的循环移位,对于带进位的循环移位,就是把溢出位的作用给进位。
13.定点数运算