LeetCode题解Python溢出处理疑问:掩码法是否因无限精度失效?
LeetCode 137. Single Number II 溢出处理解析
题解中溢出检测与处理的逻辑
先看题解最后处理溢出的代码段:
if loner >= (1 << 31): loner = loner - (1 << 32)
这段代码的作用是把32位补码表示的负数转换成Python的原生负整数,原因如下:
- 题目限定数值范围是
-2^31 ~ 2^31-1,即标准32位有符号整数的范围。 - 代码逐位计算32位的每一位,最终得到的
loner在Python中是无符号的32位整数值(Python整数是无限精度,不会自动识别32位的符号位)。 - 当
loner >= 1 << 31(即2^31)时,说明这个32位数值的最高有效位(第31位,从0开始计数)被置位,按照32位有符号整数规则,这是一个负数。 - 减法修正的原理:32位补码中,负数
x对应的无符号值是x + 2^32,因此反过来,要得到真实的负数,只需用无符号值减去2^32。比如:- 32位补码的
-1对应无符号值2^32 -1,(2^32 -1) - 2^32 = -1,得到正确结果。 - 32位补码的
-2^31对应无符号值2^31,2^31 - 2^32 = -2^31,符合范围要求。
- 32位补码的
你的疑问解答
1. Python精度无限,掩码法是否无法生效?
这个判断不完全准确:
- 直接用64位掩码(如
0x7FFFFFFFFFFFFFFF)确实没用,因为我们处理的是32位数值。但针对32位场景,掩码法是可以生效的,关键是要针对32位的符号位做处理,而非用更大位数的掩码。
2. 掩码法的逻辑与减法修正的对比
先看LeetCode 371中使用的掩码处理代码:
MASK = 0xFFFFFFFF loner = ~(loner ^ MASK)
这段代码的本质和减法修正等价,都是把32位无符号值转换成Python的有符号整数,推导过程如下:
0xFFFFFFFF是32位全1的掩码,loner ^ MASK会对loner的低32位按位取反。- Python中
~y等价于-y -1,结合上面的取反操作:
假设loner是32位补码的负数,比如0xFFFFFFFF(对应-1):loner ^ MASK = 0,~0 = -1,得到正确结果。
再比如loner = 0x80000000(对应-2^31):loner ^ MASK = 0x7FFFFFFF,~0x7FFFFFFF = -2147483648,即-2^31,符合要求。
两种方法的对比:
- 减法修正:逻辑更直观,容易理解,直接基于补码的数学关系推导。
- 掩码法:代码更简洁,但需要对Python的位运算规则有清晰认识,本质和减法修正没有区别,不存在谁更规范的说法,取决于个人习惯和场景。
内容的提问来源于stack exchange,提问作者Craig Yang
相关产品推荐
相关产品推荐

