zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【C++】位运算实现加减乘除

C++ 实现 运算 加减乘除
2023-09-14 09:07:07 时间
#include<iostream>
#include<assert.h>
using namespace std;

// 位运算实现加减乘除

int myAdd(int num1, int num2)
{
    if (num2 == 0)    return num1;
    int sum = 0, carry = 0;
    sum = num1 ^ num2;    // 按位抑或
    carry = (num1 & num2) << 1;
    return myAdd(sum, carry);
}

int myAddIter(int num1, int num2)
{
    int ret = 0;
    while (num2)
    {
        ret = num1 ^ num2;
        num2 = (num1 & num2) << 1;
        num1 = ret;
    }
    return ret;
}

int myNeg(int num1)
{
    // 正数到负数的补码表示: 取反加1
    return myAdd(~num1, 1);
}

int myMinus(int num1, int num2)
{
    return myAdd(num1, myNeg(num2));
}

// (2^0)*k0 + (2^1)*k1 + (2 ^2)*k2 + ... + (2^31)*k31
int myPosMulti(int num1, int num2)
{
    int ret = 0;
    while (num2)
    {
        if (num2 & 1)    // 对应当前num2的最低位是1
            ret = myAdd(ret, num1);
        num1 <<= 1;    // num1 = num1 * 2
        num2 >>= 1;    // num2的当前位用过了就右移
    }
    return ret;
}

int myMultiply(int num1, int num2)
{
    if (num1 >= 0 && num2 >= 0)
        return myPosMulti(num1, num2);
    if (num1 < 0 && num2 >= 0)
        return myNeg(myPosMulti(myNeg(num1), num2));
    if (num1 >= 0 && num2 < 0)
        return myNeg(myPosMulti(num1, myNeg(num2)));
    if (num1 < 0 && num2 < 0)
        return myPosMulti(myNeg(num1), myNeg(num2));
}

// 除法就是由乘法的过程逆推,依次减掉(如果x够减的)y^(2^31),y^(2^30),...y^8,y^4,y^2,y^1。减掉相应数量的y就在结果加上相应的数量。
int myPosDiv(int num1, int num2)
{
    num1 = num1 > 0 ? num1 : myNeg(num1);
    num2 = num2 > 0 ? num2 : myNeg(num2);
    if (num1 < num2)
        return 0;
    long long op = num2;
    int ret = 0;
    int flag;
    int curBit = 0;
    assert(num2 != 0);
    while (op <= num1)
    {
        op <<= 1;
        ++curBit;
    }
    op >>= 1;
    --curBit;

    while (op >= num2)
    {
        if (num1 >= op)
        {
            num1 -= op;
            ret += 1 << curBit;
        }
        op >>= 1;
        --curBit;
    }
    return ret;
}

int myPosDivByMinus(int num1, int num2)
{
    int ret = 0;
    while (num1 >= num2)
    {
        num1 = myMinus(num1, num2);
        ret = myAdd(ret, 1);
    }
    return ret;
}

int myPosComp(int num1, int num2)
{
    bool isZero(int);
    int temp = 1;
    num2 = num1 ^ num2;
    if (isZero(num2))    return 0;
    while (num2 >>= 1)
        temp <<= 1;
    return temp & num1;
}


int myDivide(int num1, int num2)
{
    if ((num1 > 0 && num2 > 0) || (num1 < 0 && num2 < 0))
        return myPosDiv(num1, num2);
    else
        return myNeg(myPosDiv(num1,num2));
}

bool isNeg(int num)
{
    return num & 0x8000;
}

bool isZero(int num)
{
    return !(num & 0xFFFF);
}

bool isPos(int num)
{
    return !(num & 0x8000) && (num & 0xFFFF);
}

//int myMod(int a, int b)
//{
//
//}

int divide(int dividend, int divisor) {
    int ret = 0;
    long long curDividend, curDivisor, op;
    bool flag;
    int curBit = 0; // 记录商的1在哪一位
    if (divisor == 0)   return INT_MAX; // 往负数方向溢出咋整
    if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0))
        flag = 0;   // 负数
    else
        flag = 1;

    curDividend = abs(dividend);
    curDivisor = abs(divisor);

    if (curDividend < curDivisor)   return 0;

    op = curDivisor;
    while (op <= curDividend)
    {
        ++curBit;
        op = op << 1;
    }
    op = op >> 1;
    --curBit;

    while (op >= curDivisor)
    {
        if (curDividend >= op)
        {
            curDividend -= op;
            ret += 1 << curBit;
        }
        op = op >> 1;
        --curBit;
    }

    if (flag)
        return ret;
    return -ret;
}

int main()
{
    //INT_MIN -2147483648 INT_MIN 2147483647
    int a = INT_MAX;    //
    int b = -1;
    cout << "myAdd: " << myAdd(a, b) << endl;
    cout << "myMinus: " << myMinus(a, b) << endl;
    cout << "myMultiply: " << myMultiply(a, b) << endl;
    cout << "myDivide: " << myDivide(a, b) << endl;
    // -1010369383, -2147483648
    cout << "Leetcode: " << divide(-1010369383, INT_MIN) << endl;
    //cout << "myMod: " << myMod(a, b) << endl;
    system("pause");
    return 1;
}