動機
當初是自幹加法器與2補數… 該學會用bit operation了,這操作太神啦!!
Problem
Given two integers a
and b
, return the sum of the two integers without using the operators +
and -
.
Example 1:
Input: a = 1, b = 2Output: 3
Example 2:
Input: a = 2, b = 3Output: 5
Constraints:
-1000 <= a, b <= 1000
2的補數
就是讓 n + ?? = 0
0與n的binary都是確定的,那麼??
的binary是多少?
先退一步,如果加總的結果會把每個位元都轉成1的話,這樣我們以此再加1是不是就是0了!!
0001 + 1111 = (1)0000
所以??
是n的not加1,有辦法用算數的方式得到補數嗎?
如果把10000
減掉0001
就是-1
,
所以把2^(bits+1)-val
就是補數
正數的最大值(最小的負數)在哪?
?? + ?? = (1)0000
??
等於1000
,也就是2^bits-1
所以如果遇到大於等於2^bits-1
的數字要轉成負數,val-2^bits
Sol
def twos_complement(val, nbits):
"""Compute the 2's complement of int value val"""
if val < 0:
val = (1 << nbits) + val
else:
if (val & (1 << (nbits - 1))) != 0:
# If sign bit is set.
# compute negative value.
val = val - (1 << nbits)
return val
def adder(a,b):
a = int(a)
b = int(b)
return [a ^ b, a & b]
class Solution:
def getSum(self, a: int, b: int) -> int:
a = twos_complement(a,33)
b = twos_complement(b,33)
#print(format(a,'b').zfill(33),format(b,'b').zfill(33))
a = iter(reversed(list(format(a,'b').zfill(33))))
b = iter(reversed(list(format(b,'b').zfill(33))))
c = []
carry = 0
for _ in range(33):
aa = next(a)
bb = next(b)
tmp, cc1 = adder(aa,bb)
s, cc2 = adder(tmp, carry)
carry = cc1 | cc2
c.append(s)
c.reverse()
#print(c)
c = ''.join(str(tmp) for tmp in c)
#print(c)
c = twos_complement(int(c,2),33)
return c
Case Study
1與1相會要進位,用and加左移來模擬 01,01都會變成1,00,11都要變成0,這就只能是xor了
所以就是上面的步驟反覆做直到沒有可以進位的數為止,太神啦!!!
class Solution(object):
def getSum(self, a, b):
# 32 bits integer max
MAX = 0x7FFFFFFF
# 32 bits interger min
MIN = 0x80000000
# mask to get last 32 bits
mask = 0xFFFFFFFF
while b != 0:
# ^ get different bits and & gets double 1s, << moves carry
a, b = (a ^ b) & mask, ((a & b) << 1) & mask
return a if a <= MAX else ~(a ^ mask)