我想解决一个老问题:
Write a function that add two [integer] numbers A and B. You should not use + or any arithmetic operators.
最好的解决方案是这样的,引用自“LintCode-A+B Problem”:
For a + b in any base, we can treat the plus as two part: 1. a + b without carry; 2. the carry generated by a +b. The a+b then equals to part 1 plus part 2. If part1+part2 generates more carry, we can then repeat this procedure, until there is no carry.
我能理解这个算法,而且一切看起来都很好,所以我在lintcode上用下面粘贴的代码测试了它。
class Solution:
"""
@param a: The first integer
@param b: The second integer
@return: The sum of a and b
"""
def aplusb(self, a, b):
while b != 0:
carry = a & b
a = a ^ b
b = carry << 1
return a
但令人惊讶的是,它在测试用例中给了我Time Limit Exceeded
错误。所以我在本地运行它并为每个循环打印a,b:
(-8, 8)
(-16, 16)
(-32, 32)
(-64, 64)
(-128, 128)
(-256, 256)
(-512, 512)
(-1024, 1024)
(-2048, 2048)
(-4096, 4096)
(-8192, 8192)
(-16384, 16384)
(-32768, 32768)
(-65536, 65536)
(-131072, 131072)
...
计算是正确的,所以我认为这种算法对于这样的输入不起作用,但是当我在C++中写同样的算法时,它只是工作:
class Solution {
public:
int aplusb(int a, int b) {
while (b!=0){
int carry = a & b;
a = a^b;
b = carry << 1;
}
return a;
}
};
我不知道该问什么,基本上问题是:
-4
的二进制2补码表示是是的,我的意思是在左边有无穷多个
1
;这是一个二进制重复数字。从技术上讲,4
也是一个重复的数字:只是在左边重复
0
。你的加法问题是
运算符
^
、<<
和&
在计算无限多个二进制数字时没有问题,但问题是有无限多个进位,而您一次只计算一个数字。这永远不会结束。因此,你必须认识到这个算法何时会陷入这种情况,并采取其他措施来解释它。
<>你在C/C++中没有遇到这个问题,因为,例如,如果{{CD8}}是32位,那么除了最右边的31位数字之外的所有数字都会崩溃成一个比特,所以剩下的所有的都一次携带。
然而,从技术上讲,左移一个
int
的含义是将值作为整数,而不是位模式,因此,如果两个最重要的位carry
永远不同,则调用未定义的行为,因为这样carry << 1
将产生溢出)。根据@Hurkyl的出色解释,我使用python实现了无限二的恭维表示这一事实,逐步完成了
a=4
和b=-4
的算法:很明显,需要有一个有效的截断来模拟类似于32位有符号2的恭维整数。一旦进位气泡上升超过最高位,算法就需要停止。以下操作似乎有效:
结果:
问题是负数,或者负数是如何表示的。在Python中,整数具有任意的精度,而C++的It是32位或64位。所以在Python中,必须单独处理负数,例如减法,或者手动限制位的数量。
相关问题 更多 >
编程相关推荐