二进制补码 加 减 取模 java代码实现

APU

实现二进制补码的加法

(全加法实现)

首先声明两个int类型的变量 CFOF,用来模拟加法过程中的进位和溢出

对于加法结果的每一位,都是由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,哪一个更大
因为二进制补码可以理解为值盒子
值盒子,哪一个高位先有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;
    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值