数据结构--只用位运算实现加减乘除操作

实现加法

https://www.jianshu.com/p/7bba031b11e7

https://blog.csdn.net/ojshilu/article/details/11179911

public class Arithmetic {
    /**
     * 两数之和
     * 异或运算(^)得出的是和 sum
     * 与运算(&)得出的是进位  carry
     * 将sum和carry<<1继续相加即可
     * @param a
     * @param b
     * @return
     */
    public static int add(int a, int b){
        if(b == 0) return a;
        int sum = a ^ b;
        int carry = (a & b) << 1;
        return add(sum, carry);
    }

    /**
     * 两数之差
     * a - b实际上就是a + (-b)
     * 在实际中做减法时,-b是用补码  取反 + 1
     * @param a
     * @param b
     * @return
     */
    public static int substract(int a, int b){
        return add(a, negative(b));
    }

    /**
     * 求一个数的相反数 取反再+1
     * @param a
     * @return
     */
    public static int negative(int a){
        return add(~a, 1);
    }


    /**
     * 求一个数的符号,
     * 0则为正数,否则就返回-1
     * @param a
     * @return
     */
    public static int sign(int a){
        return a >> 31;
    }

    /**
     * 将数变为正数,如果数为正数,则为其本身,如果为负数,则变为其相反数
     * @param a
     * @return
     */
    public static int positive(int a){
        int flag = sign( a );

        if(flag == 0) return a;
        else return negative( a );
    }

    /**
     * 两数乘积
     * 先计算两个正数的乘积,然后符号最后加上
     * 两个正数的乘积,a, b  就是 a 进行 b 次加法
     * 注意最后加上符号
     * @param a
     * @param b
     * @return
     */
    public static int multiply(int a, int b){
        boolean flag = sign(a) != sign(b);
        a = positive( a );
        b = positive( b );
        int res = 0;
        while(b > 0){
            res = add(res, a);
            b = substract( b, 1 );
        }
        if(flag){
            return negative( res );
        }
        return res;
    }

    /**
     * 两数之积
     * 0101
     * 0110
     *
     *    0000
     *   0101
     *  0101
     * 0000
     * 对应位置求和即可
     *
     * 根据 b 每一位为 1 就将 a 左移一位加到 res 上即可,为 0 就什么都不做
     * @param a
     * @param b
     * @return
     */
    public static int multiplay1(int a, int b){
        boolean flag = (sign(a) != sign(b));
        a = positive( a );
        b = positive( b );

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

        if(flag) return negative( res );
        return res;

    }


    /**
     * 两数的商
     * 用a - b,一直减,知道a < b时,此时减的次数就是商,a 就是余数
     * 注意还有符号
     * @param a
     * @param b
     * @return
     */
    public static int divide(int a, int b){
        if(b == 0) return -1;
        boolean flag = (sign(a) != sign(b));
        int res = 0;
        a = positive( a );
        b = positive( b );
        while(a >= b){
            res = add(res, 1);
            a = substract( a, b );
        }
        if(flag){
            return negative( res );
        }
        return res;
    }


    /**
     * 两数之商
     * 上面那种方法,每次都是减去一个 b,如果 b 太小的话,会计算的很慢
     * 而如果以 b 的 2^i 倍开始减的话,如果 a 够减,则结果上加上 2 ^ i 倍
     * 首先要判断 a 是否大于 b 的 2 ^ i倍
     * 改为判断 a / (2 ^ i) 与 b 的大小,这样可以防止溢出
     *  a * (1 >> i) = a >> i
     *  (a >> i) >= b
     * @param a
     * @param b
     * @return
     */
    public static int divide1(int a, int b){
        if(b == 0) return -1;

        boolean flag = (sign( a ) != sign( b ));
        a = positive( a );
        b = positive( b );

        int res = 0;
        int i = 31;
        while(i >= 0){
            if((a >> i) >= b){
                res = add( res, 1 << i );
                a = substract( a, b << i );
            }
            i = substract( i, 1 );
        }
        if(flag) return negative( res );
        return res;
    }


    public static void main(String[] args){
        System.out.println(add( 7, 5 ));
        System.out.println(substract( 7, 5 ));
        System.out.println(negative(-33));
        System.out.println(sign( -23 ));
        System.out.println(positive( 3 ));
        System.out.println(multiply( -7, -5 ));
        System.out.println(divide( -35, -5 ));
        System.out.println(divide1( -35, -5 ));

        System.out.println(multiplay1( -7, 5 ));
    }
}

  

 

posted @ 2018-05-09 11:16  SkyeAngel  阅读(479)  评论(0编辑  收藏  举报