//用位运算进行加法

package Arithmetic;

/**
 * @author 真他喵的学不动咯
 * @create 2022-08-13--10:24
 */

//https://leetcode-cn.com/problems/divide-two-integers/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china
public class addit {   //用位运算进行加法
    //异或 ^  等同于无进位相加
    //  0110110
    //  1110111
    //  1000001
    //与 &   等同于进位
    //a  0101110
    //b  0010100
    //c  0000100
    // c=a&b
    //把 c<1  ,这就是进位信息
    // c<1 就是 001000
    //  a+b=a^b+a&b;   加法=无进位相加+只有进位信息
    public static int add(int a,int b){
        int sum=a;
        while (b!=0){    //直到进位信息为0,跳出循环   // sum=无进位信息+进位信息 因为不能出现加号,所以要等进位信息是0的时候,跳出循环
            sum=a^b;            //无进位相加信息
            b=(a&b)<<1;         //进位信息  b'
            a=sum;              //加起来  a'
        }  //说到底还是对位进行了加法,所以这些代码要在循环里面
        return sum;
    }
    //减法
    //  a-b = a+b的相反数
    //  b的相反数:  ~b+1
    //  add(a,~b+1)  等价于  add(a,add(~b,1))
    public static int negNum(int n){   //n的相反数
        return add(~n,1);
    }
    public static int minus(int a,int b){
        return add(a,negNum(b));    //a+b的相反数
    }
    //乘法   》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》不理解

    public static int multi(int a,int b){
        int res=0;
        while (b != 0){
            if ((b&1) !=0){   //判断当前位是不是0
                res=add(res,a);   //把当前这一位算入结果中
            }
            a <<=1;  //a左移1位     用符号位补充
            b >>>=1; //b不带符号右移1位    用0补位
        }
        return res;

    }
    //判断是不是负数
    public static boolean isNeg(int n){
        return n<0;
    }
    //除法
    public static int div(int a,int b){
        //把除数和被除数都转化成正数
        int x=isNeg(a)? negNum(a):a;
        int y=isNeg(b)? negNum(b):b;
        int res=0;  //res是结果
        // x/y
        // 用x够y,而不是用y够x,y够x容易发生溢出成负数
        for (int i=30;i>=0;i=minus(i,1)){  //x固定移动31次
            if ((x>>i)>=y){  // x右移i位,和y比大小,比y小就是0,不比y小就是1
            res |=(1<<i);
            x=minus(x,y<<i);
            }
        }
        return isNeg(a)^isNeg(b)? negNum(res):res;   //补符号
        //如果ab符号不一样,取负号符号返回;   negNum()取负号
        //如果ab符号一样,直接返回
        }
        //系统最小值没办法转成正值、
    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){   //如果除数是b**,都会向下取整为0,直接返回0
            return 0;
        }else if (a==Integer.MIN_VALUE){   //如果被除数a是系统最小
            //相当于把最小值分成最大值和另一个数,把这两个数用写的div方法除下来,再加上,就又回到了最小值扽开除的结果
            if (b==negNum(1)){   //力扣约定: 系统最小值/1=系统最大值    实际上应该是系统最大值+1
                return Integer.MAX_VALUE;
            }else{
                //a/b
                //(a+1)/b==c
                //a-(b*c)=d
                //d/b=e
                //c+e
                int c=div(add(a,1),a);   //c=(a+1)/b
                return add(c,div(minus(a,multi(b,c)),b));  //c+[a-(b*c)]/b
            }

        }else{  //正常情况
            return div(a,b);
        }
    }
}

//day05  01''10''37

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值