1. 程式人生 > >九度OJ-題目1507:不用加減乘除做加法

九度OJ-題目1507:不用加減乘除做加法

題目連結地址:

題目描述:
寫一個函式,求兩個整數之和,要求在函式體內不得使用+、-、*、/四則運算子號。

輸入:
輸入可能包含多個測試樣例。
對於每個測試案例,輸入為兩個整數m和n(1<=m,n<=1000000)。

輸出:
對應每個測試案例,輸出m+n的值。

樣例輸入:
3  4
7  9

樣例輸出:
7
16

解題思路:

不用加減乘除實現加法,那自然就想到神奇的位運算了。既然是位運算,那肯定就要把十進位制數字轉換成二進位制了。
二進位制數的加法滿足以下規則:
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 10
二進位制數的異或運算滿足以下規則:
0 ^ 0 = 0,0 ^ 1 = 1,1 ^ 0 = 1,1 ^ 1 = 0
二進位制數的按位與運算滿足以下規則:
0 & 0 = 0,0 & 1 = 0,1 & 0 = 0,1 & 1 = 1
因此可以用兩個數的異或結果表示加法過程中所得到的臨時和,用兩個數按位與的結果再左移一位表示加法過程中的進位。
用位運算求a+b的過程如下:
 (1)將a ^ b做為當前和結果jg,(a & b) << 1做為a+b的進位jw;
 (2)如果jw為0,則jg就是a + b的結果,否則將jg賦值給a,jw賦值給b,跳轉到步驟(1)繼續執行。
舉個栗子,a = 7,b = 9,求a + b的過程如下:
1)將7轉換為二進位制為0111,將9轉換為二進位制是1001,
      則jg = a ^ b = 0111 ^ 1001 = 1110,
         jw = (a & b) << 1 = (0111 & 1001) << 1 = 0010;
2)令a = jg = 1110,b = jw = 0010,
      則jg = a ^ b = 1110 ^ 0010 = 1100,
         jw = (a & b) << 1 = (1110 & 0010) << 1 = 0100;
3)令a = jg = 1100,b = jw = 0100,
      則jg = a ^ b = 1100 ^ 0100= 1000,
         jw = (a & b) << 1 = (1100 & 0100) << 1 = 1000;
4)令a = jg = 1000,b = jw = 1000,
     則jg = a ^ b = 1000 ^ 1000= 0000,
        jw = (a & b) << 1 = (1000 & 1000) << 1 = 10000;
5)令a = jg = 00000,b = jw = 10000,
     則jg = a ^ b = 00000 ^ 10000 = 10000,
        jw = (a & b) << 1 = (00000 & 10000) << 1 = 0,
因為jw = 0,所以此時可以得出a+b = 10000 = 16。
AC程式碼如下:

#include<stdio.h>
 
/**
* 0 ^ 0 = 0,0 ^ 1 = 1,1 ^ 0 = 1,1 ^ 1 = 0
* 0 & 0 = 0,0 & 1 = 0,1 & 0 = 0,1 & 1 = 1
* a + b 的結果由加法結果和加法進位組成
* (1)用 a ^ b 表示a + b的結果jg
* (2)用 (a & b) << 1 表示a + b的進位jw
* (3)再讓結果jg與進位jw重複(1)(2)步驟,直至進位jw為0時,可以得到最後的求和運算結果jg
* @param a  使用者輸入的第一個整數
* @param b  使用者輸入的第二個整數
* @return jg  返回使用者輸入的兩個整數之和
*/
int additionWithoutPlus(int a,int b)
{
  int jg = a;       // 存放"加法"的結果
  int jw = b;       // 存放"加法"的進位
  int temp_a,temp_b; // temp_a存放臨時的求和結果,temp_b存放臨時的求和進位
  while(jw)
  {
      temp_a = jg;
      temp_b = jw;
      jg = temp_a ^ temp_b;          // 通過異或得到兩個二進位制數字的和
      jw = (temp_a & temp_b) << 1;   // 通過按位與再向左移動一位得到兩個二進位制數字相加得到的進位
  }
  return jg;
}
 
int main()
{
    int sum;
    int m,n;
    while(EOF != scanf("%d%d",&m,&n))
    {
        sum = additionWithoutPlus(m,n);
        printf("%d\n",sum);
    }
    return 0;
}
 
/**************************************************************
    Problem: 1507
    User: blueshell
    Language: C
    Result: Accepted
    Time:10 ms
    Memory:912 kb
****************************************************************/