实现一个Add函数,让两个数相加,但是不能使用+、-、*、/等四则运算符。ps:也不能用++、--等等

分析:这又是一道考察发散思维的很有意思的题目。当我们习以为常的东西被限制使用的时候,如何突破常规去思考,就是解决这个问题的关键所在。
看到的这个题目,首先我们可以分析人们是如何做十进制的加法的,比如是如何得出5+17=22这个结果的。
实际上,我们可以分成三步的:
第一步只做各位相加不进位,此时相加的结果是12(个位数5和7相加不要进位是2,十位数0和1相加结果是1);
第二步做进位,5+7中有进位,进位的值是10;第三步把前面两个结果加起来,12+10的结果是22,刚好5+17=22。
对数字做运算,除了四则运算之外,也就只剩下位运算了。位运算是针对二进制的,我们也就以二进制再来分析一下前面的三步走策略对二进制是不是也管用。
5的二进制是101,17的二进制10001。还是试着把计算分成三步:
第一步各位相加但不计进位,得到的结果是10100(最后一位两个数都是1,相加的结果是二进制的10。这一步不计进位,因此结果仍然是0);
第二步记下进位。在这个例子中只在最后一位相加时产生一个进位,结果是二进制的10;
第三步把前两步的结果相加,得到的结果是10110,正好是22。由此可见三步走的策略对二进制也是管用的。
接下来我们试着把二进制上的加法用位运算来替代。

第一步不考虑进位,对每一位相加。0加0与 1加1的结果都0,0加1与1加0的结果都是1。我们可以注意到,这和异或的结果是一样的。

接着考虑第二步进位,对0加0、0加1、1加0而言,都不会产生进位,只有1加1时,会向前产生一个进位。此时我们可以想象成是两个数先做位与运算,然后再向左移动一位。只有两个数都是1的时候,位与得到的结果是1,其余都是0。

第三步把前两个步骤的结果相加。如果我们定义一个函数Add(),第三步就相当于输入前两步骤的结果来递归调用自己。

[cpp]  view plain  copy
  1. class Solution   
  2. public:  
  3.     int sum = 0;  
  4.     int tmp=0;  
  5.     int Add(int num1, int num2)   
  6.     {  
  7.         if (num2 == 0)  
  8.         {  
  9.             return num1;  
  10.         }  
  11.         else  
  12.         {  
  13.             //第一步,相加不进位    
  14.             sum = num1 ^ num2;  
  15.             //第二步,求得进位的值    
  16.             tmp = (num1 & num2) << 1;  
  17.             //第三步,sum和tmp相加    
  18.             return Add(sum, tmp);  
  19.         }  
  20.     }  
[cpp]  view plain  copy
  1. //非递归版:  
  2.   
  3. /* 
  4. *两个数异或:相当于每一位相加,而不考虑进位; 
  5. *两个数相与,并左移一位:相当于求得进位; 
  6. *将两个新得到的数进行add操作,得到的结果和原本两个数相加相同, 
  7. *这样会把num2变得越来越小,知道为0是,则两个数的和直接就变成num1. 
  8. */  
  9.   
  10.      int Add(int num1, int num2)  
  11.      {  
  12.         while (num2 != 0)  
  13.         {  
  14.             int temp = num1^num2;  
  15.             num2 = (num1&num2) << 1;  
  16.             num1 = temp;  
  17.         }  
  18.         return num1;  
  19.     }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是实现要求的完整代码: ```c++ #include <iostream> #include <cstring> using namespace std; #define MAX_LENGTH 100 // 函数声明 void add(char *a, char *b, char *result); void subtract(char *a, char *b, char *result); void removeLeadingZero(char *num); int main() { char op; char num1[MAX_LENGTH + 1], num2[MAX_LENGTH + 1], result[MAX_LENGTH + 2]; cin >> num1 >> op >> num2; if (op == '+') { add(num1, num2, result); cout << result << endl; } else if (op == '-') { subtract(num1, num2, result); cout << result << endl; } return 0; } // 加法运算 void add(char *a, char *b, char *result) { int len1 = strlen(a); int len2 = strlen(b); int len = max(len1, len2); int carry = 0; // 进位 int i, j, k; for (i = len1 - 1, j = len2 - 1, k = len - 1; k >= 0; i--, j--, k--) { int x = i >= 0 ? a[i] - '0' : 0; int y = j >= 0 ? b[j] - '0' : 0; int sum = x + y + carry; result[k] = sum % 10 + '0'; carry = sum / 10; } if (carry) { result[k] = carry + '0'; result[len + 1] = '\0'; } else { result[len] = '\0'; } } // 减法运算 void subtract(char *a, char *b, char *result) { int len1 = strlen(a); int len2 = strlen(b); int len = max(len1, len2); int borrow = 0; // 借位 int i, j, k; for (i = len1 - 1, j = len2 - 1, k = len - 1; k >= 0; i--, j--, k--) { int x = i >= 0 ? a[i] - '0' : 0; int y = j >= 0 ? b[j] - '0' : 0; int diff = x - y - borrow; if (diff < 0) { diff += 10; borrow = 1; } else { borrow = 0; } result[k] = diff + '0'; } removeLeadingZero(result); if (strlen(result) == 0) { result[0] = '0'; result[1] = '\0'; } else if (borrow) { int len = strlen(result); for (int i = len; i >= 1; i--) { result[i] = result[i - 1]; } result[0] = '-'; result[len + 1] = '\0'; } } // 去除前导零 void removeLeadingZero(char *num) { int len = strlen(num); int i; for (i = 0; i < len; i++) { if (num[i] != '0') { break; } } if (i == len) { num[0] = '0'; num[1] = '\0'; } else { for (int j = 0; j < len - i; j++) { num[j] = num[j + i]; } num[len - i] = '\0'; } } ``` 该程序首先读入个字串和运算,然后根据运算调用相应的函数进行加法或减法运算,最后输出运算结果。其中,加法运算采用逐位相加的方法,减法运算采用逐位相减的方法,并且在需要借位时将 borrow 置为 1,需要进位时将 carry 置为 1。在计算完结果后需要去除前导零,并且如果结果为负数,则在最前面加上负号。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值