面试题 47(*),不用加减乘除做加法(位运算易想到,怎么用就是个技术活了)(附 不定义新变量前提下交换两数的方法)
用位运算是第一反应,a^b可以算出当前位的结果, a&b可以算出是否进位。
但是接下来怎么办呢?
我的方法是,每次从两个数取一位,然后计算,进位。直到两个数都没有位可取了(往左看都只有0),最后做一个进位。
我的代码:
#include <stdio.h> int Sum(int a, int b){ int finalRes = 0; int count = 0; int prevAcc = 0, curAcc= 0; int p = 0, q = 0; int bitRes = 0; while(a | b){ p = a&1; q = b&1; a = a >> 1; b = b >> 1; int temp = p ^ q; curAcc = p & q; bitRes = temp ^ prevAcc; prevAcc = curAcc | (temp&prevAcc); finalRes |= (bitRes << (count++)); } finalRes |= prevAcc << count; return finalRes; } // ====================测试代码==================== void Test(int num1, int num2, int expected) { int result = Sum(num1, num2); if(result == expected) printf("%d + %d is %d. Passed\n", num1, num2, result); else printf("%d + %d is %d. Failed\n", num1, num2, result); } int main() { Test(1, 2, 3); Test(111, 899, 1010); Test(5, 2, 7); Test(1, 100, 101); Test(3, 0, 3); Test(0, 5, 5); Test(2, 8, 10); }
白板一次error free bug free,但是,写到一半就明白这个解法是不全面的。。
因为没有考虑负数。
补码表示下的负数,并不能通过每次提取一位的方法来倒腾。
这种思路对于上次facebook的面试题倒是可以用,当时的题目是:两个只含有'0' '1'的字符串,计算两个字符串相加的结果。
在这种情况下,答案的解法确实让人佩服。
书上代码:
int Add(int num1, int num2) { int sum, carry; do { sum = num1 ^ num2; carry = (num1 & num2) << 1; num1 = sum; num2 = carry; } while(num2 != 0); return num1; }
整体计算,carry表示各个位上计算后的进位,将carry左移一位,再加上sum,就是要求的结果。如何算carry和sum相加的结果呢?
同样可以利用上述方法。
循环思路出现。
循环终止条件是carry为0,也就是说,不再有进位了。
引申:
顺便提一提怎样在不定义新的变量的情况下交换两个int的方法。假设要交换a和b。
四则运算法,这个比较熟悉了。
a = a + b;
b = a - b;
a = a - b;
位运算法,不常用,但是更简单:
a = a ^ b;
b = a ^ b;
a = a ^ b;
------------------------------------------------
Felix原创,转载请注明出处,感谢博客园!
posted on 2014-03-11 10:09 Felix Fang 阅读(445) 评论(0) 编辑 收藏 举报