位运算实现

位运算效率高,直接怼代码,里面有注解

public class Code02_Bit {
    public static void main(String[] args) {
        int a, b;
        int sumTimes = 100000;
        System.out.println("开始测试");
        while (sumTimes-- > 1) {
            a = (int) (Math.random() * 10);
            b = (int) (Math.random() * 20);
           /* if ((a + b) != bitAdd(a, b)) {
                System.out.println(a + "+" + b + "=" + bitAdd(a, b));
                throw new RuntimeException("位运算加法出现问题了!!");
            }
            if ((a - b) != bitMinus(a, b)) {
                throw new RuntimeException("位运算减法出现问题了!!");
            }*/
            if ((a * b) != bitMulti(a, b)) {
                throw new RuntimeException("位运算乘法出现问题了!!");
            }
        }
        System.out.println("结束测试");
        System.out.println("开始测试取反");
        a = 10;
        System.out.println(String.format("%s的取反(~%s)等于%s", a, a, ~a));
        System.out.println("结束测试取反");
    }

    /**
     * 两数相加(最好的方式,没有出现“+”号)
     *
     * @param a
     * @param b
     * @return
     */
    private static int bitAdd(int a, int b) {
        // 不能为sum=0,否则当b=0,但a不等于0时,返回sum=0
        int sum = a;
        while (b != 0) {
            sum = a ^ b;
            b = (a & b) << 1;
            a = sum;
        }
        return sum;
    }

    /**
     * 两数相减
     * 相当于a+(-b):a加上b的相反数
     *
     * @param a
     * @param b
     * @return
     */
    private static int bitMinus(int a, int b) {
        return bitAdd(a, negNum(b));
    }

    /**
     * 两数相乘
     * 4*6 <==>00000100*00000110
     *    00000100
     *  * 00000110
     *   -----------
     *    00001000
     *+   00010000
     *  ------------
     *    00011000
     * =>16+8=24
     *
     * @param a
     * @param b
     * @return
     */
    private static int bitMulti(int a, int b) {
        int res = 0;
        while (b != 0) {
            if ((b & 1) != 0) {
                res = bitAdd(res, a);
            }
            a <<= 1;
            b >>>= 1;
        }
        return res;
    }

    /**
     * 两数相除,不能直接计算Integer.MIN_VALUE,
     * 因为这里涉及取绝对值
     * 24/4 = 6 <==>
     *  00000100*00000110
     *  00000100*00000100 + 00000100*00000010
     *  00010000+00001000
     *  =16+8=24
     *
     *  注意:向下取整 18/7 《=》14/7 = 2
     * @param a
     * @param b
     * @return
     */
    public static int biDiv(int a, int b) {
        // 如果是负数,转成相反数
        int x = isNeg(a) ? negNum(a) : a;
        int y = isNeg(b) ? negNum(b) : b;
        int res = 0;
        // x/y
        // 非负数,所以不需要从31位开始
        for (int i = 30; i >=0 ; i--) {
            if ((x >> i) >= y){
                res |= (1<<i);
                x = bitMinus(x,y<<i);
            }
        }
        // 正正|负负得正,正负|负正得负
        return isNeg(a) ^ isNeg(b) ? negNum(res) :res;
    }

    /**
     * 位运算除法统一入口
     *
     * @param a
     * @param b
     * @return
     */
    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 {
                /**
                 * example: 假设范围-15~14
                 * 计算 -15/3?
                 * 由于|-15|越界了,明显不行
                 * 思路:(-15+1)/3 = -4
                 * -15-(3*(-4)) = -3
                 * -3/3 = -1
                 * 结果:-4+(-1)=-5
                 */
                int c = biDiv(bitAdd(a, 1), b);
                return bitAdd(c, biDiv(bitMinus(a, bitMulti(c, b)), b));
            }
        } else {
            return biDiv(a, b);
        }
    }
    /**
     * 是否是正数
     * @param n
     * @return
     */
    public static boolean isNeg(int n){
        return n < 0;
    }

    /**
     * 求a的相反数
     * <p>
     * ~9 = -10
     * ~10 = -11
     *
     * @param a
     * @return
     */
    private static int negNum(int a) {
        return bitAdd(~a, 1);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值