Sum of Two Integers
2016-07-11 12:37
417 查看
Calculate the sum of two integers a and b, but you are not allowed to use the operator
Example:
Given a = 1 and b = 2, return 3.
Credits:
Special thanks to @fujiaozhu for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
本题是考察计算机内部实现加法的原理。
一位二进制加法
首先给出一位二进制加法的真值表,然后我们通过分析真值表来得出如果进行二进制加法的规则。
一位二进制加法真值表:(对应于硬件中的半加器)
分析上面一位二进制加法的真值表,可以看出和其实就是x XOR y的结果。而进位恰好是x AND y的结果。下面提供XOR和AND的真值表,进行验证。
x XOR y真值表:
x AND y真值表:
多位二进制加法
因此进行一位二进制加法,只要对x和y进行XOR和AND运算就可以得出和以及进位。如果要求多位的二进制加法,则要把低位传上来的进位也要计算进去。修改一位二进制加法的真值表,在输入部分中加入低位传入的进位,然后对计算结果进行修正就可以得到多位二进制加法的真值表了。
多位二进制加法真值表:(对应于硬件中的全加器)
分析上面的真值表就可以总结出,多位二进制加法的规则了。如下:
sum = (x XOR y) XOR icarry
ocarry = (x AND y) OR (icarry AND (x XOR y)) = (x AND y) OR (y AND icarry) OR (icarry AND x)
利用以上的分析结果,可将x, y的每一位级联计算,先计算x和y的第零位,该位的输入进位(icarry=0)为零,将计算所得的进位传入到x和y的第一位的计算中,依次进行直到计算完最高位为止,此时将每一位计算所得的和连接起来就是最终的和,最高位计算所得的进位就是最终的进位。至此,二进制的加法应该没有什么问题了,很简单XOR为和,AND为进位。计算机中的加法也是使用这种原理来实现的,有兴趣的可以看看《编码的奥秘》这本书。
通过以上分析似乎用代码实现计算机加法的方法已经很明了了,将参加计算的x,y分别一位一位的进行XOR和AND,然后将结果打印出来,OK完事了,很简单不是吗?但问题是如果将x和y的每一位拆分,然后记录每一位计算后所得的进位,然后做为下一位的进位输入。仔细想想又似乎是问题多多啊,烦啊。其实也不然我们用代码实现的时候已经不需要再将每一位拆分计算了(如果你确实像模拟计算机硬件的执行过程也可以这么做,只是这样做很麻烦,而且计算的速度比较慢)。首先,我们通过对x和y进行&位运算,得出每一位上的进位。然后对x和y进行^位运算,得出没有加进位的和。最后将所得的和当做新的x,所得的进位往左移一位(第零位的进位输入为0)当做新的y,继续做上面的步骤,直到进位为0,此时x中保存的就是我们要求的x和y的和了。
代码如下:
+and
-.
Example:
Given a = 1 and b = 2, return 3.
Credits:
Special thanks to @fujiaozhu for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
本题是考察计算机内部实现加法的原理。
一位二进制加法
首先给出一位二进制加法的真值表,然后我们通过分析真值表来得出如果进行二进制加法的规则。
一位二进制加法真值表:(对应于硬件中的半加器)
x | y | sum | carry |
0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
x XOR y真值表:
x | y | output |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
x | y | output |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
因此进行一位二进制加法,只要对x和y进行XOR和AND运算就可以得出和以及进位。如果要求多位的二进制加法,则要把低位传上来的进位也要计算进去。修改一位二进制加法的真值表,在输入部分中加入低位传入的进位,然后对计算结果进行修正就可以得到多位二进制加法的真值表了。
多位二进制加法真值表:(对应于硬件中的全加器)
x | y | icarry | sum | ocarry |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 1 | 0 |
0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 1 |
1 | 0 | 0 | 1 | 0 |
1 | 0 | 1 | 0 | 1 |
1 | 1 | 0 | 0 | 1 |
1 | 1 | 1 | 1 | 1 |
sum = (x XOR y) XOR icarry
ocarry = (x AND y) OR (icarry AND (x XOR y)) = (x AND y) OR (y AND icarry) OR (icarry AND x)
利用以上的分析结果,可将x, y的每一位级联计算,先计算x和y的第零位,该位的输入进位(icarry=0)为零,将计算所得的进位传入到x和y的第一位的计算中,依次进行直到计算完最高位为止,此时将每一位计算所得的和连接起来就是最终的和,最高位计算所得的进位就是最终的进位。至此,二进制的加法应该没有什么问题了,很简单XOR为和,AND为进位。计算机中的加法也是使用这种原理来实现的,有兴趣的可以看看《编码的奥秘》这本书。
通过以上分析似乎用代码实现计算机加法的方法已经很明了了,将参加计算的x,y分别一位一位的进行XOR和AND,然后将结果打印出来,OK完事了,很简单不是吗?但问题是如果将x和y的每一位拆分,然后记录每一位计算后所得的进位,然后做为下一位的进位输入。仔细想想又似乎是问题多多啊,烦啊。其实也不然我们用代码实现的时候已经不需要再将每一位拆分计算了(如果你确实像模拟计算机硬件的执行过程也可以这么做,只是这样做很麻烦,而且计算的速度比较慢)。首先,我们通过对x和y进行&位运算,得出每一位上的进位。然后对x和y进行^位运算,得出没有加进位的和。最后将所得的和当做新的x,所得的进位往左移一位(第零位的进位输入为0)当做新的y,继续做上面的步骤,直到进位为0,此时x中保存的就是我们要求的x和y的和了。
代码如下:
class Solution(object): def getSum(self, a, b): """ :type a: int :type b: int :rtype: int """ while (b != 0): c = a ^ b b = (a & b) << 1 a = c return a
相关文章推荐
- C# 禁止windows程序重复运行的两种基本方法
- Linux下tar.xz tar.bz2 tar.gz 等文件的解压
- 面试题20:顺时针打印矩阵
- C语言学习笔记----realloc
- uva 12716 GCD XOR
- 263. Ugly Number && 264. Ugly Number II && 313. Super Ugly Number
- listview添加headerview需要注意的,listview自定义的item注意的焦点
- uboot 与系统内核中MTD分区的关系:
- Spring核心技术(十)——JSR-330标准注解
- java字节流与字符流之文件复制
- Spring核心技术(十)——JSR-330标准注解
- tcp三次握手协议
- JAVA XML解析
- Android开发--NDK之环境搭建
- 插件svn简单使用
- Toj 3990. I guess the gift is a bag! II
- Eclipse导入导出Preference配置文件
- Jenkins 2.0新时代:从CI到CD
- HashMap与ConcurrentHashMap的区别
- NFS网络文件系统的创建