有人可以解释这个leetcode解决方案如何与负数一起使用?

时间:2016-08-14 06:33:53

标签: python bit-manipulation

这是leetcode problem 371Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.

的解决方案

为什么我们需要MODMAX_INT以及这部分是做什么的? ~(a & MAX_INT) ^ MAX_INT

def getSum( a, b):
    """
    :type a: int
    :type b: int
    :rtype: int
    """
    MOD     = 0xFFFFFFFF
    MAX_INT = 0x7FFFFFFF
    while b != 0:
        a, b = (a ^ b) & MOD, ((a & b) << 1) & MOD
    return a if a <= MAX_INT else ~(a & MAX_INT) ^ MAX_INT

print getSum4(-4,2)
-2

解决方案来自this blog

2 个答案:

答案 0 :(得分:1)

MODMAX_INT~(a & MAX_INT) ^ MAX_INT的原因是模拟32位整数。这是必要的,因为在Python中,整数不受限制。

执行计算后,& MOD仅用于保留结果的32位最低有效位。在整数只有32位的系统中,这实际上就是这样;简单地删除额外的位。

MAX_INT的用法是正确处理32位整数的整数溢出。如果您添加0x400000000x40000000,则会获得0x80000000,这在Python中只是一个正整数。对于32位整数,这将是溢出,值等于-0x80000000

a & MAX_INT是删除最重要的位,在32位整数中基本上用作符号。 ~(...) ^ MAX_INT是一种将31位数扩展到实际使用的位数的方法。例如,如果Python只使用42位,-0x80000000将表示为0xff80000000。换句话说,只需将超出最低有效31位的每一位设置为1。 (执行~x与执行x ^ 0xff...ff相同,因此~x ^ MAX_INTx ^ (0xff..ff MAX_INT)x ^ 0xff...ff80000000相同,如果{{1}则与x | 0xff...ff80000000相同“仅使用”31位)。

当然,Python在概念上没有使用固定数量的位,但你可以看一下它就好像将无限数量的位设置为1.它只是不存储所有那些位,就像它不会将所有0位都存储为正数(例如0x00 ... 001)。

另一种方法是x,你可以使用第32位已正确设置。

答案 1 :(得分:-1)

我并不感到惊讶,你很难理解这段代码,但它确实可行,但我建议你从头开始。首先要确保掌握位运算符,数字integer representation和负数two's complement。然后尝试通过几个测试来理解这两个更简单的函数:

def add_32bits_buggy(a, b):
    MOD = 0xFFFFFFFF

    while (a != 0):
        c = (b & a) & MOD
        b = (b ^ a) & MOD
        a = (c << 1) & MOD

    return b


def add_32bits(a, b):
    MOD = 0xFFFFFFFF
    MAX_INT = 0x7FFFFFFF

    while (a != 0):
        c = (b & a) & MOD
        b = (b ^ a) & MOD
        a = (c << 1) & MOD

    if b <= MAX_INT:
        return b
    else:
        return ~(b & MAX_INT) ^ MAX_INT

# value to test edge_cases
max_v = 0xFFFFFFFF

# Positive integers
i = 1
while i <= max_v:
    i *= 2
    a, b = max_v + 1, i
    print "{0:10d}\t{1:10d}".format(
        add_32bits(a, b), add_32bits_buggy(a, b),
    )

print '-'*80

# Negative integers
i = 1
while i <= max_v:
    i *= 2
    a, b = max_v + 1, i
    print "{0:10d}\t{1:10d}".format(
        add_32bits(a, -b), add_32bits_buggy(a, -b),
    )

add_32bits_buggy函数将回答您的问题&#34;为什么我们需要MODMAX_INT,这部分是做什么的? ~(a & MAX_INT) ^ MAX_INT&#34 ;.然后add_32bits(相当于原始代码)将显示这些案例是如何因为返回而得到修复的。

希望它有所帮助。