位運算實現加減乘除

n1ce2cv發表於2024-09-21

29. 兩數相除

#include <iostream>

using namespace std;

class Solution {
public:

    int add(int a, int b) {
        int res = a;
        while (b != 0) {
            // 無進位相加的結果
            res = a ^ b;
            // 相加時每一位的進位資訊
            b = (a & b) << 1;
            // 無進位相加的結果
            a = res;
            // 如果進位資訊 b 不全是 0 的話,仍需將進位資訊 b 與無進位相加的結果 a 繼續相加
        }
        return res;
    }

    // 補碼:原碼按位取反再加一
    int neg(int n) {
        return add(~n, 1);
    }

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

    int multiply(int a, int b) {
        int res = 0;
        while (b != 0) {
            if ((b & 1) != 0)
                res = add(res, a);
            // 算數左移
            a <<= 1;
            // 邏輯右移
            b = (unsigned int) b >> 1;
        }
        return res;
    }

    // 必須保證 a 和 b 都不是整數最小值,返回 a 除以 b 的結果
    int div(int a, int b) {
        int x = a < 0 ? neg(a) : a;
        int y = b < 0 ? neg(b) : b;
        int res = 0;
        for (int i = 30; i >= 0; i = minus(i, 1)) {
            if ((x >> i) >= y) {
                res |= (1 << i);
                x = minus(x, y << i);
            }
        }
        return a < 0 ^ b < 0 ? neg(res) : res;
    }

    const int MIN = INT_MIN;
    const int MAX = INT_MAX;

    int divide(int a, int b) {
        // a 和 b 都是整數最小
        if (a == MIN && b == MIN) return 1;
        // a 和 b 都不是整數最小,正常除
        if (a != MIN && b != MIN) return div(a, b);
        // a 不是整數最小,b 是整數最小
        if (b == MIN) return 0;
        // a 是整數最小,b 是 -1,返回整數最大,因為題目裡明確這麼說了
        if (b == neg(1)) return MAX;
        // a 是整數最小,b 不是整數最小,b 也不是 -1
        a = add(a, b > 0 ? b : neg(b));
        int res = div(a, b);
        int offset = b > 0 ? neg(1) : 1;
        return add(res, offset);
    }
};

相關文章