位运算的应用----->实现加减乘除

首先我们想想位操作符->  ^ (异或)

异或可以相当于无进位相加

同时我们的进位为信息也可以用 (x & y)<<1来表示

那么我么的“+”可以相当于是无进位相加数 + 进位信息。

但是我们模拟实验“+”所以不能出现加号。

什么时候不需要加上进位信息--->进位信息为0的时候。

那么我们就可以知道,位运算实现“+”

 public static int add(int a,int b){
        int x = a>b ? a : b;
        int y = x==a ? b : a;
        int sum = 0;
        while( y!=0 ){
            sum = x ^ y;
            y = (x & y)<<1;
            x = sum;
        }
        return sum;
    }

同时位运算实现减号---->就是

 private static int negNum(int n){
        return add(~n,1);
    }
   public static int minus(int x,int y){
        return add(x,negNum(y));
   }

将y--->进行取反+1就是-y.

x-y = x + (-y);


乘号

首先我们先想想我们是如何实现乘法的

我们先看这个20---。

首先20的第一个数字是0.那么我们用0乘以12所得为零。-------第一阶段结果为0。

其次20的第二个数字为2.那么我们是先将2*12,然后将所得的数字的后面加一个0,------第二阶段的结果为240.

那么我们可以想象,我们所进行的十进位的数字的乘法,实际上的步骤是:

将乘数的第0位数字,单独和被乘数相乘,相乘所得数向前移动0位,然后得到一个阶段的数字

将乘数的第1位数字,单独和被乘数相乘,相乘所得数向前移动1位,然后得到一个阶段的数字

将乘数的第2位数字,单独和被乘数相乘,相乘所得数向前移动2位,然后得到一个阶段的数字

将乘数的第3位数字,单独和被乘数相乘,相乘所得数向前移动3位,然后得到一个阶段的数字

...................

直到乘数的所有非零的数字都进行上诉运算后,然后将所有得到的阶段数字进行相加,就得到乘法所得到的数字。

但是当我们使用到二进制位也是如此。

 public static int muli(int a,int b){
       int sum = 0;
       while(b != 0){
           if((b & 1)!=0){
               sum = add(sum,a);
           }
           a<<=1;
           b>>>=1;
       }
       return sum;
   }

接下来我们说说除法。

我们先了解一下我们平时是如何进行除法运算的。

首先我们十进制的除法运算,是首先从头开始

首先我们先从被除数中重头找到大于除数的数字,然后我们利用那么我们就能够算最大为几倍,然后相减。剩下的数字我们就继续找到,知道我们的被除数小于我们的除数的时候我们就得出结论

private static int div(int a,int b){
        int x = isNeg(a) ? negNum(a) : a;
        int y = isNeg(b) ? negNum(b) : b;
        int res = 0;
        for(int i = 30;i>=0; i = muli(i,1)){
            if((x>>i)>=y){
                res |= (1<<i);
                x = minus(x, y<< i);
            }
        }
        return isNeg(a) ^ isNeg(b) ? negNum(res) : res;
   }

同时我们还是有一个问题需要我们来考虑,就是我们的这个类型是一个int类型的。当我们出现Integer.MIN_VALUE---->最小值的时候我们就没有办法转化成正数。那么我们就是需要特殊问题特殊处理了

1.除数和被除数都是Integer.MIN_VALUE----->直接返回1.

2.除数是Integer.MIN_VALUE,被除数不是。------>返回0.

3.除数不是,被除数是---->特殊情况特殊考虑。

4.除数和被除数都不是Integer.MIN_VALUE----->直接调用

特殊情况的讨论:

首先知道系统最小值是的绝对值比系统最大值的绝对值大1.

其次我们的Integer.MIN_VALUE--->无法转成正数,但是我们可以先将Integer.MIN_VALUE+1,这样就可以转成正数,同时我们算出来的余数在加上1,再进行一次除法计算,将两次得到结果相加就是我们特殊情况的处理

   private static int div(int a,int b){
        int x = isNeg(a) ? negNum(a) : a;
        int y = isNeg(b) ? negNum(b) : b;
        int res = 0;
        for(int i = 30;i>=0; i = minus(i,1)){
            if((x>>i)>=y){
                res |= (1<<i);
                x = minus(x, y<< i);
            }
        }
        return isNeg(a) != isNeg(b) ? negNum(res) : res;
   }
   public static int divide(int a,int b){
        if(a == Integer.MIN_VALUE && b==Integer.MIN_VALUE){
            return 1;
        }else if(b == Integer.MIN_VALUE){
            return 0;
        }else if(a == Integer.MIN_VALUE){
            if(b == negNum(1)){
                return Integer.MAX_VALUE;
            }else{
                int c = div(add(a,1),b);
                return add(c,div(minus(a,muli(c,b)),b));
            }
        }else{
            return div(a,b);
        }
   }

-------------------------------------------

    public static int add(int a,int b){
        int x = a>b ? a : b;
        int y = x==a ? b : a;
        int sum = 0;
        while( y!=0 ){
            sum = x ^ y;
            y = (x & y)<<1;
            x = sum;
        }
        return sum;
    }
    private static int negNum(int n){
        return add(~n,1);
    }
   public static int minus(int x,int y){
        return add(x,negNum(y));
   }
   public static int muli(int a,int b){
       int sum = 0;
       while(b != 0){
           if((b & 1)!=0){
               sum = add(sum,a);
           }
           a<<=1;
           b>>>=1;
       }
       return sum;
   }
   private static boolean isNeg(int x){
        return x<0;
   }
   private static int div(int a,int b){
        int x = isNeg(a) ? negNum(a) : a;
        int y = isNeg(b) ? negNum(b) : b;
        int res = 0;
        for(int i = 30;i>=0; i = minus(i,1)){
            if((x>>i)>=y){
                res |= (1<<i);
                x = minus(x, y<< i);
            }
        }
        return isNeg(a) != isNeg(b) ? negNum(res) : res;
   }
   public static int divide(int a,int b){
        if(a == Integer.MIN_VALUE && b==Integer.MIN_VALUE){
            return 1;
        }else if(b == Integer.MIN_VALUE){
            return 0;
        }else if(a == Integer.MIN_VALUE){
            if(b == negNum(1)){
                return Integer.MAX_VALUE;
            }else{
                int c = div(add(a,1),b);
                return add(c,div(minus(a,muli(c,b)),b));
            }
        }else{
            return div(a,b);
        }
   }
   private static int mod(int x,int y){
        if((y & (minus(y,1)))==0){
            return x & (minus(y,1));
        }else{
            for(int i = 30;i>=0; i = minus(i,1)){
                if((x>>i)>=y){
                    x = minus(x,y<<i);
                }
            }
            return x;
        }
   }
    
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值