如果和和两个加数的按位异或均为负,这意味着什么?

What does it mean if the bitwise XOR of the sum and two addends are both negative?

比如有3个long类型的变量,我们加上ab得到s:

long a, b, s;
...
s = a + b

现在 ((s^a) < 0 && (s^b) < 0) 是什么意思?

我在 Python 的 source code 中看到了这样的支票:

    if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
        /* INLINE: int + int */
        register long a, b, i;
        a = PyInt_AS_LONG(v);
        b = PyInt_AS_LONG(w);
        i = a + b;
        if ((i^a) < 0 && (i^b) < 0)
            goto slow_iadd;
        x = PyInt_FromLong(i);
    }

我不明白这怎么可能。

如果 (s^a) < 0,则 sa 的符号位必须为 1,因此 sa(但不是两者) 必须为负。 sb 相同。所以要么 s 是负数而 ab 都是正数,要么 s 是正数而 ab 都是负数。这两种情况似乎都不可能。

当然,除非你计算整数 overflow/underflow。

这段代码是错误的。

假设有符号整数按位异或的通常 2 的补码规则,则

(s^a) < 0
如果 sa 将它们的符号位设置为相反的值,则

就是这种情况。因此,

((s^a) < 0 && (s^b) < 0)

表示 sab 的符号不同,因此必须具有等号(假装 0 是正数)。如果你把两个等号的整数相加得到的结果是不同的符号,那肯定是溢出了,所以这就是溢出检查。

如果我们假设有符号溢出回绕,那么 sab 正好在溢出发生时具有相反的符号。但是,有符号溢出是未定义的行为。计算 s 已经是错误的;我们需要在不实际执行操作的情况下检查是否会发生溢出。

Python 不应该这样做。您可以在 Python 2 source code for int.__add__:

中看到它应该做什么
/* casts in the line below avoid undefined behaviour on overflow */
x = (long)((unsigned long)a + b);
if ((x^a) >= 0 || (x^b) >= 0)

它应该转换为 unsigned 以获得定义的溢出行为。由于 Python 错误跟踪器上的 issue 7406,在 5 个不同的地方引入了 cast-to-unsigned 修复,但看起来他们遗漏了一个地方,或者 INPLACE_ADD 可能被更改了自那时候起。我在追踪器上留言了