Sword finger offer -- add without addition, subtraction, multiplication and division

Meaning: write a function and find the sum of two integers. It is required that the four operation symbols +, -, *, / should not be used in the function body.

Analysis: before I did my own manual yy, I used binary to do bit operation directly, and then I didn't consider negative number, i.e. WA directly. Then I carefully analyzed the number in four cases (a > 0, b > 0; a > = 0, B < = 0; a < 0, b > 0; a < 0, B < 0). Then I calculated it. It was OK to pay attention to carry or borrow.

Reference code:

class Solution {
public:
    int Add(int num1, int num2)
    {
        int ans = 0;
        int sign = 1;//The sign bits of and are+
        bool flag = true;//add 
        if( num1 >= 0 && num2 <= 0)
        {
            num2 = abs(num2);
            flag = false;//Do subtraction
            if( num1 < num2)
            {
                sign = -1;//Symbol bit is-
                swap(num1,num2);
            }
        }
        else if( num1 < 0 && num2 > 0)
        {
            num1 = abs(num1);
            flag = false;
            if( num1 > num2)
                sign = -1;
            else
                swap(num1,num2);
        }
        else if( num1 < 0 && num2 < 0)
        {
            sign = -1;
            num1 = abs(num1);
            num2 = abs(num2);
        }

        bool carry = false;
        bool borrow = false;
        int cnt = 0;
        while( num1 || num2)
        {
            if( ( num1&1) && ( num2&1))//It's all 1 addition carry (if it has carry, it needs to be calculated), subtraction is 0 (with special treatment of borrow), it doesn't matter if it's 0
            {
                if( flag)//+
                {
                    if( carry)
                        ans = ans^(1<<cnt);
                    carry = true;
                }
                else
                {
                    if( borrow)
                        ans = ans^(1<<cnt);
                }
            }
            else if( ( num1&1) && !( num2&1))//Before 1, after 0,
            {
                if( flag)//+
                {
                    if( !carry)
                        ans = ans^(1<<cnt);
                }
                else//-
                {
                    if( !borrow)//No borrow, direct reduction
                        ans = ans^(1<<cnt);
                    else
                        borrow = false;
                }
            }
            else if( !( num1&1) && ( num2&1))//Before 0 after 1
            {
                if( flag)
                {
                    if( !carry)
                        ans = ans^(1<<cnt);
                }
                else
                {
                    if( !borrow)
                        ans = ans^(1<<cnt);
                    borrow = true;
                }
            }
            else if( !( num1&1) && !( num2&1))//0 0
            {
                if( flag)
                {
                    if( carry)
                    {
                        ans = ans^(1<<cnt);
                        carry = false;
                    }
                }
                else
                {
                    if( borrow)
                        ans = ans^(1<<cnt);
                }
            }
            cnt++;
            num1 >>= 1;
            num2 >>= 1;
        }
        if( flag && carry)
            ans = ans^(1<<cnt);
        return ans*sign;
    }
};

However, it seems that my practice is too complicated, the code is a little long, and then I take a look at Baidu= =) emmm found that there is a simpler way, which is to use the exclusive or + shift operation. Each time we get two results, one is the result of exclusive or of two numbers, the other is the result of carry. In fact, we still need to find the sum of the two numbers. We have been cycling this operation to guide carry to 0, and then we get the final answer. In this way, we don't need to worry about positive and negative numbers. It's simple.

class Solution {
public:
    int Add(int num1, int num2)
    {
        int ans = 0;
        int carry;
        while( true)
        {
            ans = num1^num2;
            carry = (num1&num2)<<1;
            if( !carry)
                return ans;
            num1 = ans;
            num2 = carry;
        }
    }
};

Posted by nathus on Tue, 05 May 2020 01:35:21 -0700