文章目录
定点数溢出判断
加减法溢出的必要条件
- 从真值
a
,
b
a,b
a,b的角度分析:加减法溢出的可能只有两种:仅当两个符号相同的数相加或两个符号相异的数相减才可能产生溢出,简称:同号加,异号减
-
对于加法
- 只有在正数加正数和负数加负数两种情况下才可能出现溢出,
- 符号不同的两个数相加是不会溢出的。
-
对于减法
- 只有在正数减负数或负数减正数两种情况下才可能出现溢出,
- 符号相同的两个数相减是不会溢出的。
-
- 就是如果 a + b a+b a+b发生了溢出, ∣ a + b ∣ = ∣ a ∣ + ∣ b ∣ |a+b|=|a|+|b| ∣a+b∣=∣a∣+∣b∣;如果 a − b a-b a−b发生了溢出,则 ∣ a − b ∣ = ∣ a ∣ + ∣ b ∣ |a-b|=|a|+|b| ∣a−b∣=∣a∣+∣b∣
补码加减法溢出
- 计算机中的定点数是用补码表示的,并且由于补码的特性,总是把减法转为加法操作,这就不需要考虑减法操作的溢出了
- 计算机使用补码表示整数,由于减法运算在机器中是用加法器实现的,因此可得出如下结论:
- 不论是作加法还是减法,只要实际参加操作的两个数符号相同,结果又与原操作数的符号不同,即为溢出。
- 我们只需要考虑两个数相加溢出的情况,因为加法溢出的条件是连个加数是同号的,也就是补码都是0开头或者都是1开头的情况下才可能发生
-
比如:两个正数相加,结果的符号位却为 1 (结果为负);
-
一个负数减去某个正数,结果的符号位却为 0 (结果为正)
-
溢出类型
正溢出是指两个正数相加结果是一个过大的正数导致机器字长内无法正确表示的溢出
负溢出是指两个负数相加结果是一个过小的负数导致机器字长内无法正确表示的溢出
简单讲就是正数相加导致的溢出就是正溢出,负数相加导致的溢出称为负溢出
定点数补码运算判断溢出方法👺
- 方法使用对象:定点数补码
- 定点数补码的加减运算溢出判断的方法有 3 种
- 设两个操作数分被是: A = A s , x 1 x 2 ⋯ x n A=A_{s},x_{1}x_{2}\cdots{x_{n}} A=As,x1x2⋯xn, B = B s , y 1 y 2 ⋯ y n B=B_{s},y_{1}y_{2}\cdots{y_{n}} B=Bs,y1y2⋯yn,两数的符号位分被位 A s , B s A_{s},B_{s} As,Bs;
- 并且令两数之和的结果为 S = A + B = S s , z 1 z 2 ⋯ z n S=A+B=S_{s},z_{1}z_{2}\cdots{z_{n}} S=A+B=Ss,z1z2⋯zn,其中 S s S_{s} Ss是结果 S S S的符号位,注意 S s S_{s} Ss不一定等等于 A s + B s A_{s}+B_{s} As+Bs,因为它还收到数值位是否会通过进位影响到符号位
下面介绍三种判断方法
用一位符号位并根据加数和结果的符号位判断溢出
-
溢出的条件就是 A s = B s ≠ S s A_{s}=B_{s}\neq{S_{s}} As=Bs=Ss
-
用逻辑表达式描述: A s B s S s A_sB_sS_s AsBsSs在取 001 , 110 001,110 001,110这两种情况会且一定会溢出
-
设逻辑函数 f ( A s , B s , S s ) f(A_{s},B_{s},S_{s}) f(As,Bs,Ss),当 f = 1 f=1 f=1时表示溢出,否则没有溢出
-
则逻辑函数 f f f应该满足 f ( 0 , 0 , 1 ) = 1 f(0,0,1)=1 f(0,0,1)=1, f ( 1 , 1 , 0 ) = 1 f(1,1,0)=1 f(1,1,0)=1,其余情况都为0
-
通过数字逻辑的知识或卡诺图等方法可以推导出相应的逻辑表达式(标准与或式)
-
V = f ( A s , B s , S s ) V=f(A_{s},B_{s},S_{s}) V=f(As,Bs,Ss)= A s B s S s ‾ + A s ‾ B s ‾ S s A_sB_s\overline{S_s}+\overline{A_s}\ \overline{B_s}S_s AsBsSs+As BsSs
-
从概率论的角度看,事件 V = { 发生溢出 } V=\set{发生溢出} V={发生溢出}的符号表示为:
-
V
=
A
s
B
s
S
s
‾
∪
A
s
‾
B
s
‾
S
s
V=A_sB_s\overline{S_s}\cup\overline{A_s}\ \overline{B_s}S_s
V=AsBsSs∪As BsSs
- V 1 = A s B s S s ‾ V_1=A_sB_s\overline{S_s} V1=AsBsSs
- V 2 = A s ‾ B s ‾ S s V_2=\overline{A_s}\ \overline{B_s}S_s V2=As BsSs
- V = V 1 ∪ V 2 , V 1 与 V 2 至少一个事件发生 , 则表示溢出 V=V_1\cup{V_2},V_1与V_2至少一个事件发生,则表示溢出 V=V1∪V2,V1与V2至少一个事件发生,则表示溢出
-
V
=
A
s
B
s
S
s
‾
∪
A
s
‾
B
s
‾
S
s
V=A_sB_s\overline{S_s}\cup\overline{A_s}\ \overline{B_s}S_s
V=AsBsSs∪As BsSs
-
例
- 下面以机器字长为5位(含1位符号位,位数值位)为例,说明机器是如何判断溢出的。
-
机器字长为5位的补码所对应的真值范围为-8~+7,运算结果一旦超过这个范围即为溢出。
- A = − 0.1011 A=-0.1011 A=−0.1011, B = − 0.0111 B=-0.0111 B=−0.0111
- C ( A ) = 1.0101 C(A)=1.0101 C(A)=1.0101, C ( B ) = 1.1001 C(B)=1.1001 C(B)=1.1001
- C ( A + B ) = C ( A ) + C ( B ) = 1.0101 + 1.1001 = 10.1110 C(A+B)=C(A)+C(B)=1.0101+1.1001=10.1110 C(A+B)=C(A)+C(B)=1.0101+1.1001=10.1110,对结果取 ( m o d 2 ) \pmod{2} (mod2)丢弃最高位1,结果为 0.1110 0.1110 0.1110
- A s = 1 , B s = 1 , S s = 0 A_{s}=1,B_{s}=1,S_{s}=0 As=1,Bs=1,Ss=0
- V = A s B s S s ‾ + A s ‾ B s ‾ S s V=A_sB_s\overline{S_s}+\overline{A_s}\ \overline{B_s}S_s V=AsBsSs+As BsSs= 1 1 1,说明上面的运算结果发生了溢出
用一位符号位并根据最高数值位进位情况判断
为了便于讨论,我们将确定加法结果 S S S的 z 1 z_{1} z1时产生的进位记为 C 1 C_{1} C1,类似的,确定 z i z_{i} zi时产生的进位记为 C i C_{i} Ci,并且 C i ∈ { 0 , 1 } , ( i = 1 , 2 , ⋯ , n + 1 ) C_{i}\in\set{0,1},(i=1,2,\cdots,n+1) Ci∈{0,1},(i=1,2,⋯,n+1);
在计算两个 r r r进制数相加时,从低位对齐,在求和的过程中,低位向高位进位最多进位1,因为两个最大数码 ( r − 1 ) + ( r − 1 ) = 2 r − 2 < 2 r (r-1)+(r-1)=2r-2<{2r} (r−1)+(r−1)=2r−2<2r,例如9+9=18,也只能向高位进1,如果次低位两个本位数码为 r − 1 r-1 r−1,那么及时再加上低位进1,结果也只有 2 r − 1 < 2 r 2r-1<2r 2r−1<2r,向更高位也只能进1,由此可见,直到最高位被确定,中途出现的进位不可能超过1,如果不进位的,可以称进位为0;事实上从进位计数制的特点,两个最大 n n n位 r r r进制数相加 2 ( r n − 1 ) 2(r^{n}-1) 2(rn−1),最终一定小于 2 r n 2r^{n} 2rn,因此最多只能进位 1 1 1
显然,两个二进制数再加上来自低位的进位结果为 x i + y i + C i − 1 ⩽ 1 1 2 x_{i}+y_{i}+C_{i-1}\leqslant{11_{2}} xi+yi+Ci−1⩽112,向高位进位的 C n − i ⩽ 1 C_{n-i}\leqslant{1} Cn−i⩽1
记 C i = C a r r y ( x i + y i + C i + 1 ) C_{i}=Carry(x_{i}+y_{i}+C_{i+1}) Ci=Carry(xi+yi+Ci+1), ( C n + 1 = 0 ) (C_{n+1}=0) (Cn+1=0), i = 1 , 2 , ⋯ , n i=1,2,\cdots,n i=1,2,⋯,n;其中 C a r r y Carry Carry函数表示求进位
确定 S s S_{s} Ss时,即 A s + B s + C 1 A_{s}+B_{s}+C_{1} As+Bs+C1的进位结果记为 C 0 C_{0} C0
事实上,如果 C n = C n − 1 C_{n}=C_{n-1} Cn=Cn−1,那么说明加法 A + B A+B A+B没有溢出,否则溢出
分两类情况讨论:
-
若两个正数相加发生溢出,则是因为结果符号位 S s S_{s} Ss本该是0却变成 1 1 1,并且这个1是在确定 z 1 z_{1} z1的时候发生进位到符号位产生的,即 C 1 = 1 C_{1}=1 C1=1,而 C 0 = C a r r y ( x 1 + y 1 + C 1 ) C_{0}=Carry(x_1+y_{1}+C_{1}) C0=Carry(x1+y1+C1)= C a r r y ( 0 + 0 + 1 ) Carry(0+0+1) Carry(0+0+1)=0;此时 C 0 ≠ C 1 C_{0}\neq{C_{1}} C0=C1;
- 而如果 C 1 = 0 C_{1}=0 C1=0,则 C 0 = 0 C_{0}=0 C0=0,就不会发生过溢出,此时 C 0 = C 1 C_{0}=C_{1} C0=C1
-
若两个负数相加发生溢出,则是因为符号位本 S s S_{s} Ss本该是1却变成0,
-
确定 z 1 z_{1} z1的时候没有向符号位进位1,即 C 1 = 0 C_{1}=0 C1=0,
-
符号位本位的进位情况 C 0 = C a r r y ( A s + B s + C 1 ) = C a r r y ( 1 + 1 + 0 ) = 1 C_{0}=Carry(A_{s}+B_{s}+C_{1})=Carry(1+1+0)=1 C0=Carry(As+Bs+C1)=Carry(1+1+0)=1,此时 C 0 ≠ C 1 C_{0}\neq{C_{1}} C0=C1
-
而如果 C 1 = 1 C_{1}=1 C1=1,则 C 0 = 1 C_{0}=1 C0=1,就不会发生溢出,此时 C 0 = C 1 C_{0}=C_{1} C0=C1
-
-
综上 C 0 ≠ C 1 C_{0}\neq{C_{1}} C0=C1时运算结果溢出,否则不溢出
溢出判断逻辑表达式
如果我们令
V
=
1
V=1
V=1是表示溢出,
V
=
0
V=0
V=0表示没有溢出,容易想到上述
C
0
,
C
1
C_{0},C_{1}
C0,C1取值和
V
V
V的取值可以用异或运算
⊕
\oplus
⊕来表示
V
=
C
s
⊕
C
1
V=C_s\oplus{C_1}
V=Cs⊕C1
双符号位变形补码判断溢出
假设机器字长相对于相加的两个数来说足够大,即相加不会出现溢出,那么符号位一定不会受到来自数值位加法进位的干扰
考虑到两个 r r r进制数相加,数值位结果最多向高位进位1,比如两个 n n n位数相加后,结果达到 n + 1 n+1 n+1位,但是不可能达到 n + 2 n+2 n+2位数值位;这个特点对于二进制同样满足
在机器字长(寄存器位数)有限的情况下,如果我们使用2位符号位(让数值位位数减少1位),虽然可以表示的数值范围看起来会受影响(少了一半),但是便于我们判断是否发生了溢出
双符号位组合分析
在双符号位的情况下,第一位符号位(高位符号位)是两个加数相加后结果的真正符号位,而第二位符号位可以充当数值位进位(可能进到符号位)的缓冲
双符号位补码称为变形补码,和单符号位补码有明显区别:使用 00 00 00作为整数的符号位,使用 11 11 11作为负数的符号位
正数相加
两个正数相加不溢出时,数值位相加不向符号位进位,此时结果的符号位是 00 00 00;
如果溢出,则数值位相加会向符号位进位,此时结果的符号位是 01 01 01(此时称为正溢出)
负数相加
两个负数相加不溢出时,数值位相加要向符号位进位(才不会让本应为负数的结果变为正数),此时结果的符号位是 11 11 11;(此时最高符号位也会进位,结果的最高位到最低符号位是111,对其取模丢弃掉最高位符号位的进位,剩下2位符号位11)
如果溢出,则数值位相加没有向符号位进位,此时结果符号位为 10 10 10(此时称为负溢出)
结果的真正符号位
综上,无论是否溢出,两数相加的结果中第一位符号位结果的真正符号位
判断公式👺
综上所述,若令 A + B = S A+B=S A+B=S,且 S S S的两个符号位为 S 1 S 2 S_{1}S_{2} S1S2,那么 S 1 S 2 = 00 , 11 S_{1}S_{2}=00,11 S1S2=00,11两种情况下不溢出,而 S 1 S 2 = 01 , 10 S_{1}S_{2}=01,10 S1S2=01,10两种情况下,会发生溢出
如果我们令
V
=
1
V=1
V=1是表示溢出,
V
=
0
V=0
V=0表示没有溢出,容易想到上述
S
1
,
S
2
S_{1},S_{2}
S1,S2取值和
V
V
V的取值可以用异或运算
⊕
\oplus
⊕来表示
V
=
S
1
⊕
S
2
V=S_{1}\oplus{S_{2}}
V=S1⊕S2
补充说明
- 两个正数相加,数值位向第二位符号位进位,结果的2个符号位为 01 01 01,这种情况下说明发生了溢出(第二位符号位认为两个正数相加出现负数结果,实际结果的符号以第一位符号位为准)
- 两个负数相加,数值位向第二位符号位进位,则又会导致第一位符号位进位,得到111,结果的2个符号位为
11
11
11(对于小数将
111
m
o
d
2
2
111\mod{2^{2}}
111mod22丢弃最高位,剩下两位符号位11;对于整数,将求和结果取模
2
n
+
2
2^{n+2}
2n+2(
n
n
n表示数值位位数),可以丢掉最高位的1,剩下两个符号位11),这种情况表示没有溢出
- 这里参考单符号位取 ( m o d 2 ) \pmod{2} (mod2)的做法,双符号位取 ( m o d 2 2 ) \pmod{2^{2}} (mod22)来丢弃最高位符号位之前的更高位进位,整数也类似
可以发现,如果两个负数相加,如果数值位部分不向符号位进位,那么符号位会是110,对其取模 4 4 4,结果为 10 10 10,这种情况是溢出的,并且是负溢出
以单符号位两个负数补码相加为例,如果数值位相加不会向 n + 1 n+1 n+1位(也就是最高位)进1,符号位 1 + 1 = 10 1+1=10 1+1=10,那么在取模的情况下(整数取模 2 n + 1 2^{n+1} 2n+1,小数取模 2 2 2),符号位将会是 0 0 0,因此两个负数相加变成了正数,这显然是溢出了,这对双符号位也是一样的,数值位相加没有向符号位进位就是溢出
双符号位定义
双符号位的补码小数定义为:
-
C 2 ( x ) = { x 0 ⩽ x < 1 4 + x = 4 − ∣ x ∣ − 1 ⩽ x < 0 ( m o d 4 ) C_{2}(x)= \begin{cases} x &0\leqslant{x}<1 \\4+x=4-|x| &-1\leqslant{x}<0 \pmod{4} \end{cases} C2(x)={x4+x=4−∣x∣0⩽x<1−1⩽x<0(mod4)
- 这里的模4= 2 2 2^2 22,取模 4 4 4可以将高位符号位进位的1丢弃掉
双符号位整数补码定义为:
C
2
(
x
)
=
{
00
,
x
0
⩽
x
<
2
n
−
1
2
n
+
2
+
x
−
2
n
⩽
x
<
0
(
m
o
d
2
n
+
2
)
C_{2}(x)= \begin{cases} 00,x&0\leqslant{x}<2^{n}-1 \\2^{n+2}+x &-2^{n}\leqslant{x}<0 \pmod{2^{n+2}} \end{cases}
C2(x)={00,x2n+2+x0⩽x<2n−1−2n⩽x<0(mod2n+2)
这里的第一行
(
00
,
x
)
(00,x)
(00,x)是我们手动添加的符号位00,以此强调符号位不可省略的意义,逗号用来分割符号位和
n
n
n位数值位
硬件中的双符号方案
- 采用双符号位方案时,寄存器或主存中的操作数只需保存一位符号位即可。
- 因为任何正确的数,两个符号位的值总是相同的
- 而双符号位在加法器中又是必要的,故在相加时,寄存器中一位符号的值要同时送到加法器的两位符号位的输人端。
小结
变形补码判断溢出的原则是:当2位符号位不同时,表示溢出,否则,无溢出。
不论是否发生溢出,高位(第1位)符号位永远代表真正的符号。
- 符号位为“01”,表示溢出,又因第1位符号位为“0”,表示结果的真正符号为正,故“01”表示
正溢出
。
- 符号位为“10”,表示溢出。由于第1位符号位为1 ,则表示负溢出。
上述结论对于整数也同样适用。
在浮点机中,当阶码
用两位符号位
表示时,判断溢出的原则与小数的完全相同。