欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-11 16:15:37
...

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

题目:

确定两个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;
        
    }