只用位运算不用算术运算实现整数的加减乘除运算

参考自程序员代码面试指南

题目:

确定两个32位整数a和b,可正可负、可0。不能使用算术运算符,分别实现a和b的加减乘除运算。

要求:如果给定的a和b执行加减乘除的某些结果本来就会导致数据的溢出,那么你实现的函数补习对那些结果负责。

用位运算实现加法运算,如果在不考虑进位的情况下,a^b就是正确结果,因为0加0位0(0&0),0加1位1(0&1),1加0为1(1&0),1加1为0(1&1);

在只算进位的情况下,也就是只考虑a加b的过程中进位产生的值时什么,结果就是(a&b)<<1,因为在第i位上只有1与1相加才会产生i-1位的进位。

把完全不考虑进位的相加值与只考虑进位的产生值再相加,就是最终的结果。也就是说,一直重复这样的过程,知道进位产生的值完全消失,说明所有的过程都加完了。

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

用位运算实现减法运算,实现a-b只要实现a+(-b)即可,根据二进制数在机器中表达的规则,得到一个数的相反数,就是这个二进制数表达取反加1(补码)的结果。具体如下:

public int negNum(int n){
        return add(~n,1);
    }

    public int minus(int a,int b){
        return add(a,negNum(b));
    }

按位运算实现乘法运算。a*b的结果可以写成a*2^0*b0+2*2^1*b1+...+a*2^i*bi+...+a*2^31*b31,其中bi是表示0或1代表整数b的二进制数表达中第i位的值:

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

用位运算实现除法运算,其实就是乘法的逆运算。

public 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=31;i>-1;i=minus(i,1)){
            if((x>>i)>y){
                res|=(1<<i);
                x=minus(x,y<<i);
            }
        }
        return isNeg(a)^isNeg(b)?negNum(res):res;
        
    }

猜你喜欢

转载自blog.csdn.net/sxllllwd/article/details/82661313
今日推荐