3.1 定点数运算及溢出检测
一、定点数加法运算
$[X]_补 + [Y]_补 = [X + Y]_补 mod \\ \\ 2^{n+1}$
例如:
已知 $X = + 10010, Y = -10101$, 求$X + Y$;
$[X]_补 = 010010, [Y]_补 = 101011;$
$[X + Y]_补 = [X]_补 + [Y]_补= 010010 + 101011 = 111101$
所以$X + Y = -00011$
二、定点数减法运算
$[X - Y]_补 = [X]_补 - [Y]_补 = [X]_补 + [-Y]_补 $
(由于最后一步装换,运算器的设计可以得到简化)
例如:
已知 $[Y]_补 = 10011$,求$[-Y]_补$
$[Y]_补 = 10011$
所以$ Y = -1101, -Y = 1101$
所以$ [-Y]_补 = 01101$
对比$[Y]_补$和$[-Y]_补$可知:
通过右向左扫描$[Y]_补$, 在遇到数字$1$及之前, 直接输出遇到的数字,
遇到$1$之后, 取反输出, 即可得到$[-Y]_补$, 反之亦然!
又例如:
已知$X = +10101,Y = +10010$, 求$X - Y$
$[X]_补 = 010101, [Y]_补 = 010010, [-Y]_补 = 101110;$
$[X - Y]_补 = [X]_补 - [Y]_补 = 010101 + 101110 = 1,000011$ (首位的1溢出舍去)
所以:$X - Y = + 000011$
三、数溢出的概念和判断方法
(1)概念:运算结果超出了某种数据类型的表示范围。
例如:$X = +10010,Y = +10101$,通过补码计算得到,$X + Y = -11001$
两个整数相加由于溢出得到了负数,不符合常识(同理还有两个负数相加得到正数)
(2)检测方法:
方法1:
对操作数和运算结果的符号位进行检测,当结果的符号位与操作数的符号不相同时就表明发生了溢出
$V = X_0Y_0\overline{S_0} + \overline{X_0Y_0}S_0 $(设$X_0,Y_0$为参加运算数的符号位,$S0$为结果的符号位)
$V = 1$时有溢出,反之没有;
该逻辑表达式的含义式:当两个操作数都是正数且结果是负数 或者 两个操作数是负数且结果是正数时$V$为$1$,反之为$0$。
根据逻辑表达式,可以很容易画出相应电路;
方法2:
对最高数据位进位和符号进位进行检测;
设运算时最高数据位产生的进位为$C1$, 符号位产生的进位为$C0$
则溢出检测电路为:$ V= C0 \bigoplus C1$ (1表示溢出,0表示每溢出)
用理解的方式证明:
正数 + 负数肯定不会溢出,只用同号相加才有可能溢出;
假设是两个正数相加(除符号位部分我们分别设为$X1,Y1$)
0.X1
+ 0.Y1
----------
$C0$肯定为$0$,如果$C1 = 1$,则改变了符号位,发生了溢出;
假设是两个负数相加
1.X1
+ 1.Y1
----------
此时:$ C0 = 1$, 若$C1 = 0$,则改变了结果符号位, 发生溢出;
方法3:用变型补码
$[X]补 = X_{f1} X_{f2} . X_1 X_2 X_3 … X_n \\ \\ mod \\ \\ 2 ^{ n + 2}$
变型补码和普通补码相比有两个符号位,当数为非负数时,两个符号位为00,当数为负数时,两个符号位为11;
溢出的判断:$ V = X_{f1} \bigoplus X_{f2} $
例如: 已知$X = -10010,Y = -10101$,求$X + Y$
$[X]_补 = 11.01110,[Y]_补 = 11.01011$ (两位符号位,且都为11)
$[X + Y]_补 = [X]_补 + [Y]_补 = 1101110 + 1101011 = 1.1010001$ (首位1溢出舍弃)
$V = 1 \bigoplus 0 = 1$, 因此出现溢出;
上述三种方法根据推导出的逻辑表达式很容易设计出硬件电路来检测;
方法4;溢出判断的软件方法
也可以通过代码来检测溢出:
bool check(int a, int b)
{
int sum = a + b;
if(a < 0 && b < 0 && sum >= 0) return true;
if(a > 0 && b > 0 && sum <= 0) return true;
}
似乎软件方法更简单,但软件方法会引起流水线的停顿,降低流水线的效率;
聚聚整理得真好!以后就得看你博客学习了
是凌乱之风巨巨,太荣幸了QwQ
好巧 刚给你点完就看见你几个小时以前给我点赞了 哈哈
哈哈这太巧了吧