不用+实现两数相加

两种解法:

法一:

int aplusb(int a, int b) {
char* c = (char *)a;
return (int)&c[b];
}

解释:

举例a=2, b=3;

1.先将a的值2转化成为一个指向字符型的指针c(值为0x00000002)

2.利用数组地址是相加的原理,将c的这个地址值再加上一个b,此时c[b]返回的应该是c+b地址中存的char值,然而我们要的是c+b的地址:0x00000005,所以再取地址。然后强转int后返回。

疑惑问题分析:用char* 而不用int*?

因为char类型在C语言中是一个字节的!而int是4字节,如果char* 变量+ 1 变量前进一个字节。而若是int* c 的话,c[b]返回的就是c + b*4处的地址值。

法二:

int aplusb(int a, int b){
int sum;  //和
int carry; //进位
while(b != 0){
sum = a^b;
carry = (a&b)<<1;
a = sum;
b = carry;
}
return a;
}

解释:

(1)异或运算:

异或运算一共三种可能:

0 ^0  =  0

0^1   =  1

1^1   =  0

我们发现它刚好符合某单一位的加法的运算规则(在不考虑进位的情况下)

剩下的进位问题怎么办呢?

(2)与运算:

与运算只有在两个位都是1的情况下结果才是1。这符合进位的运算规则。所以我们用它来解决我们上面遇到的进位问题。

以7(0111)+3(0011) = 10(1010)为例:



从上面可以看到第一次相与后的结果应该是第一次进位0110,

为什么能同时计算出两位的进位呢?

这就是与运算的便捷,能及时看出其中“当前要进的位”,而不管有几位。而所谓“明显”就是进位后不知道更高位是否还需进一步进位,但是此刻满足两个1相与必须要进的位。

这也是为什么要将(进位)和(不进位时的和)分别求出来后还要进入下一次循环的原因——因为不知道加上进位后,是否更高一位还需要进一步进位。

问题:将b左移行不行?

答:不行,因为这是进位,需要将进位向左边移动,如果右移则将进位丢掉了。

猜你喜欢

转载自blog.csdn.net/fantalee/article/details/80287234