APU
实现二进制补码的加法
(全加法实现)
首先声明两个int类型的变量 CF
和OF
,用来模拟加法过程中的进位和溢出
对于加法结果的每一位,都是由CF、oprend1、oprend2三位异或产生的结果(这三个数里面有奇数个1,结果就是1)(否则偶数个1相加,这一位一定是0)
int bit = (oprend1 - '0') ^ (oprend2 - '0') ^ (cf - '0');
进位carry则是只要cf,oprend1,oprend2中只要有两个数是1,就会产生1,所以对他们用与、或操作
上述代码如下:
carry=carry = ((x - '0') & (y - '0')) | ((y - '0') & (c - '0')) | ((x - '0') & (c - '0'));
综合操作如下:
private String carry_adder(String operand1, String operand2, char c, int length) {
operand1 = impleDigits(operand1, length);
operand2 = impleDigits(operand2, length);
String res = "";
char carry = c;
for (int i = length - 1; i >= 0; i--) { //这里length不一定是4的倍数,采用更加通用的加法算法
String temp = fullAdder(operand1.charAt(i), operand2.charAt(i), carry);
carry = temp.charAt(0);
res = temp.charAt(1) + res;
}
CF = "" + carry;
return res; //注意这个方法里面溢出即有进位
}
private String fullAdder(char x, char y, char c) {
int bit = (x - '0') ^ (y - '0') ^ (c - '0'); //三位异或
int carry = ((x - '0') & (y - '0')) | ((y - '0') & (c - '0')) | ((x - '0') & (c - '0')); //有两位为1则产生进位
return "" + carry + bit; //第一个空串让后面的加法都变为字符串加法
}
需要注意的是,有进位并不等于有溢出,譬如说
111+001
,也就是-1 + 1,虽然产生进位,但是负数加正数不可能有溢出
那么溢出该怎么判断呢?
判断溢出:
如果两个相加的数符号不同,则一定不会产生溢出
如果两个操作数符号相同,那么只要相加的结果与操作数符号不同,那么就是溢出了
是否溢出 代码:
private String addOverFlow(String operand1, String operand2, String result){
int X = operand1.charAt(0) - '0';
int Y = operand2.charAt(0) - '0';
int S = result.charAt(0) - '0';
return "" + ((~X & ~Y & S) | (X & Y & ~S)); //两个操作数符号相同,和结果符号不同,则溢出
}//X=Y=1,S=0; X=Y=0,S=1;
实现二进制补码的减法
建立在二进制补码的加法基础之上,只要对减数取反,carry_adder里面的初始进位设置为1(相当于加一)就行 即**(取反加一)**
取反操作:把二进制串里面的1换成0,0换成1即可
减法:
// dest - src
String sub(String src, String dest) {
return adder(dest, negation(src), '1', 32);
}
一个较为快速地 比较两个二进制补码串大小 的方法
首先判断符号,正数肯定大于负数
如果是符号相同的情况,那么哪一个在高位先有1,哪一个更大
因为二进制补码可以理解为值盒子
private boolean isLarger(String a, String b) {
if (a.charAt(0) == '0' && b.charAt(0) == '1') {
return true;
}
if (a.charAt(0) == '1' && b.charAt(0) == '0') {
return false;
}
for (int i = 1; i < a.length(); i++) {
int diff = a.charAt(i) - b.charAt(i);
if (diff > 0) {
return true;
} else if (diff < 0) {
return false;
} else {
continue;
}
}
return false;
}
####二进制的取模 **注意取模的结果总是跟源操作数的正负号相同**
(dest mod src)
根据操作数的符号分几种情况
- 如果两个符号相同
- 都为正
- 都为负
- dest为负,src为正
- dest为
如果都为正数,那么dest-src直到减到dest<src为止
如果都为负数(dest<src -7<-2),那么dest-src直到减到dest>src为止
(如果符号不一样,把dest弄到和src符号一致,然后减去src)
如果dest>0,src<0
(7 mod -2)
那么temp=dest+src,直到temp<0为止
然后模的结果就是temp-src
(注意temp一定大于等于src)
如果dest<0,src>0
(7 mod 2)
那么temp=dest+src直到temp>0为止
然后模数等于temp-src
(注意temp一定小于等于src,所以结果一定为负数)(因为有一个负数底子:3+negative_or_zero_Number -3<0)
String imod(String src, String dest) {
//dest mod src
String temp = dest;
if (src.charAt(0) == '0' && dest.charAt(0) == '0') {
while (isLarger(temp, src) || temp.equals(src)) {
temp = sub(src, temp);
}
}
if (src.charAt(0) == '0' && dest.charAt(0) == '1') {
while (isLarger("00000000000000000000000000000000", temp) || temp.equals("00000000000000000000000000000000")) {
temp = add(src, temp);
}
temp = sub(src, temp);
}
if (src.charAt(0) == '1' && dest.charAt(0) == '0') {
while (isLarger(temp, "00000000000000000000000000000000") || temp.equals("00000000000000000000000000000000")) {
temp = add(src, temp);
}
temp = sub(src, temp);
}
if (src.charAt(0) == '1' && dest.charAt(0) == '1') {
while (isLarger(src, temp) || temp.equals(src)) {
temp = sub(src, temp);
}
}
return temp;
}