如何不使用“+”号实现加法操作?

论坛 期权论坛 期权     
匿名用户1024   2021-5-14 20:34   5308   5
我在网上看到了几种不使用加号实现加法操作的函数,但是两种的输出有一些差异,想问一下是为什么。
1.
  1. #include
  2. int add(int a,int b)
  3. {
  4.         if(a!=0 && b!=0)
  5.                   return printf("%*s%*s",a," ",b," ");
  6.         else return a==0?b:a;
  7. }
  8. int main()
  9. {
  10.         int A = 0,B = 0;
  11.         printf("Enter the two numbers to add\n");
  12.         scanf("%d %d",&A,&B);
  13.         printf("Required sum is %d",add(A,B));
  14.         return 0;
  15. }
复制代码
结果是这样的:

2.
  1. #include
  2. int add(int a,int b)
  3. {
  4.         if(a!=0 && b!=0)
  5.                   return printf("%*c%*c",a,'\r',b,'\r');
  6.         else return a==0?b:a;
  7. }
  8. int main()
  9. {
  10.         int A = 0,B = 0;
  11.         printf("Enter the two numbers to add\n");
  12.         scanf("%d %d",&A,&B);
  13.         printf("Required sum is %d",add(A,B));
  14.         return 0;
  15. }
复制代码
结果是这样的:

可以看到这两段程序只是在add函数的return返回值上有差异,那么为什么最后输出Required时一个在前面空了两格一个没有呢?
分享到 :
0 人收藏

5 个回复

倒序浏览
2#
有关回应  16级独孤 | 2021-5-14 20:34:09
答案里面很多都是直接甩代码, 我来解释一下吧。
傻瓜都能懂系列之 - 不使用
  1. +
复制代码
号实现加法:

对于这个问题,与其说是 不使用
  1. +
复制代码
号 , 还不如说是用更底层的, 用指令层级的操作来实现
  1. +
复制代码
法。
  1. +
复制代码
号这个东西本来就不是天然存在的,它本来就是用位运算实现的,我们做的只不过是自己实现一遍而已。
我们知道电路这个东西,最直接的,最好处理的就是逻辑,门电路中有 AND,OR, XOR 等操作,在实现上也很简单,可是我们真正要求计算机做的却不只是单纯的逻辑操作,而是更多的数学运算,比如加法,减法等。
那身为计算机设计者,我们就要解决一个问题,如果用最基本的 AND,OR,XOR,Shift 等电路上容易实现的操作来实现更高层次的数学运算 - 加法?
所谓
  1. XOR
复制代码
, 即是
  1. exclusive or
复制代码
, 说白了就是只有两个输入中的一个为 1 另一个为 0 的时候, 才输出 1, 都是 1 或都是 0 就输出 0, 这在硬件上实现并不难。
所谓
  1. Shift
复制代码
,  即是对一系列二进制数的左移或右移,比如 1000 , 右移一位,就变成 0100,左移一位,就变成 10000,当然前提是位数要至少是五位,硬件实现也不难。
所谓
  1. AND
复制代码
, 就是
复制代码

那么我们现在试图通过上面说的这三种运算构建出高级语言呈现给我们的,开箱即用的
  1. +
复制代码
运算符。
不管是多少进制,相加的原理都是加,进位。
但是二进制很特殊,因为它是二进制,所以很多操作可以和逻辑运算形成某种对应。
比如 101 + 111,我可以分成两部分算,一部分算”进位“,一部分算非进位那部分。
如果觉得抽象,我用十进制先举一个例子。
57 + 44 : 个位 7+4 >=10 , 进位 1, 十位 5 + 4 < 10, 进位 0, 那么进位的部分就是 10, 为什么是 10 而不是 1 呢? 因为进位本来就是向高的地方进位, 所以要 "左移一位"
非进位的那部分, 个位为 1, 十位为 9, 所以就是 91, 那么结果就是 91 + 10, 好, 那么现在问题就转换成了 91 + 10 了 —》
91 + 10:再次调用之前的操作, 进位的部分是 100, 非进位的部分是1, 那么就是 100 + 1 -》
100 + 1:进位的部分为0,非进位部分为 101, 至此,检测到进位部分为 0 ,则计算结束。
那么对于二进制来讲,计算非进位的部分,我们会发现其实就是
  1. XOR
复制代码
操作符就能解决,因为1和1相加,0和0相加,结果都是0,1和0相加结果是1,举例,而进位,则用
  1. AND
复制代码
操作符就解决, 因为当且仅当 1 和 1 都存在时, 进位才为 1, 所以是 AND。
1011 + 11: 非进位:1011 XOR 11 = 1000  进位: (1011 AND 11)
3#
有关回应  16级独孤 | 2021-5-14 20:34:10
  1. #define HALF_ADDER_S(_N,_M) ((_N)^(_M))#define HALF_ADDER_C(_N,_M) ((_N)&(_M))#define FULL_ADDER_S(_A,_B,_C) (HALF_ADDER_S(HALF_ADDER_S(_A,_B),_C))#define FULL_ADDER_C(_A,_B,_C) (HALF_ADDER_S(HALF_ADDER_C(HALF_ADDER_S(_A,_B),_C),HALF_ADDER_C(_A,_B)))#define __ADDER_1_S(_A,_B,_C) FULL_ADDER_S(_A,_B,_C)#define __ADDER_1_C(_A,_B,_C) FULL_ADDER_C(_A,_B,_C)#define __ADDER_2_S(_A,_B,_C) (__ADDER_1_S(_A&1,_B&1,_C)| \ __ADDER_1_S((_A)>>1,(_B)>>1,__ADDER_1_C(_A&1,_B&1,_C))1,(_B)>>1,__ADDER_1_C(_A&1,_B&1,_C))#define __ADDER_4_S(_A,_B,_C) (__ADDER_2_S(_A&3,_B&3,_C)| \ __ADDER_2_S((_A)>>2,(_B)>>2,__ADDER_2_C(_A&3,_B&3,_C))2,(_B)>>2,__ADDER_2_C(_A&3,_B&3,_C))#define __ADDER_8_S(_A,_B,_C) (__ADDER_4_S(_A&15,_B&15,_C)| \ __ADDER_4_S((_A)>>4,(_B)>>4,__ADDER_4_C(_A&15,_B&15,_C))4,(_B)>>4,__ADDER_4_C(_A&15,_B&15,_C))#define __ADDER_16_S(_A,_B,_C) (__ADDER_8_S(_A&255,_B&255,_C)| \ __ADDER_8_S((_A)>>8,(_B)>>8,__ADDER_8_C(_A&255,_B&255,_C))8,(_B)>>8,__ADDER_8_C(_A&255,_B&255,_C))#define __ADDER_32_S(_A,_B,_C) (__ADDER_16_S(_A&65535,_B&65535,_C)| \ __ADDER_16_S((_A)>>16,(_B)>>16,__ADDER_16_C(_A&65535,_B&65535,_C))16,(_B)>>16,__ADDER_16_C(_A&65535,_B&65535,_C))#define ADD(_A,_B) __ADDER_32_S(_A,_B,0)
复制代码
不用+号很简单,这里只用了^ & | >位运算实现32位加法.
  1. int add(int a, int b){ return ADD(a, b);}//add(1,2)//result: 3
复制代码
4#
有关回应  16级独孤 | 2021-5-14 20:34:11
[code]int adder(int lhs, int rhs){    if (lhs == 0) {        return rhs;    } else if (rhs == 0) {        return lhs;    } else {        return adder((lhs & rhs)
5#
有关回应  16级独孤 | 2021-5-14 20:34:12
[code]#include//抖机灵using namespace std;//抖机灵int a,b;//抖机灵int main(){//重说三      cin>>a>>b;      b=-b;      cout
6#
有关回应  16级独孤 | 2021-5-14 20:34:13
我觉得这道题目可以拿来面试的时候用,先让我来个正解。

如果只是单纯的不要加号,我看了题主题目中的代码其实是简单计数,并且是通过内存计数,如果21亿+21亿... 真得需要一个64位的程序才行。

话说这道题有点意思,抖机灵的a-(-b)就没必要讨论了,可以用布尔代数来解决这个问题。(这个解法有实际意义,这阐述了处理器怎么处理加法这个问题)

[code]#include int add(int a, int b){    int c = a & b, r = a ^ b;    return c == 0 ? r : add(r, c
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:136515
帖子:27303
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP