九度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
****************************************************************/


猜你喜欢

转载自blog.csdn.net/pengyan0812/article/details/46483109