如何检测数组中负数求和的溢出?现有判断逻辑存疑
问题描述
内存中有一个由补码整数组成的数组X,还有一个16位补码整数变量n(数组最大长度为32767)用来定义数组元素数量。需求是计算X中所有负数元素的和,并检测是否发生溢出。我写了Java代码实现,但用肯定会溢出的大数值测试时,代码没检测到溢出,怀疑当前的溢出判断方式有问题。
原代码如下:
public class BinaryArray { static int[]X = {3, -30000, 27, 101, 50, 0, -20000, -21, 19, 6, 4, -10}; static int n = 12; static int negSum = 0; static int pzCount = 0; static int oddCount = 0; static boolean overflow = false; public static void main(String[] args) { for(int i = 0; i<n; i++) { if(X[i] < 0) { negSum +=X[i]; } if(X[i] >= 0) { pzCount++; } if(X[i] >0 && X[i] % 2 !=0) { oddCount++; } } if(negSum > 0) { overflow = true; } System.out.println("Array negSum: " + negSum); System.out.println("Array pzCount: " + pzCount); System.out.println("Array oddCount: " + oddCount); if (overflow) { System.out.println("Overflow indicator: 1"); } else { System.out.println("Overflow indicator: 0"); } } }
问题分析与修正
你的溢出判断逻辑if(negSum > 0)存在局限性:它只捕获了负数相加溢出后结果变为正数的情况,但补码负数相加还可能出现溢出后结果仍是负数的场景(比如多个极小负数累加,溢出后落入更负的循环范围),这时候你的判断就会漏检。
正确的做法是在每次累加负数元素时即时检测溢出,判断规则为:当两个负数a和b相加时,若a + b > a(或a + b > b),则说明溢出——因为负数加负数结果应该更小,结果反而变大,就意味着发生了溢出。
修正后的代码:
public class BinaryArray { static int[]X = {3, -30000, 27, 101, 50, 0, -20000, -21, 19, 6, 4, -10}; static int n = 12; static int negSum = 0; static int pzCount = 0; static int oddCount = 0; static boolean overflow = false; public static void main(String[] args) { for(int i = 0; i<n; i++) { if(X[i] < 0) { // 累加前检查溢出:两个负数相加,结果大于任一操作数则溢出 if (negSum < 0 && X[i] < 0 && negSum + X[i] > negSum) { overflow = true; } negSum += X[i]; } if(X[i] >= 0) { pzCount++; } if(X[i] >0 && X[i] % 2 !=0) { oddCount++; } } System.out.println("Array negSum: " + negSum); System.out.println("Array pzCount: " + pzCount); System.out.println("Array oddCount: " + oddCount); System.out.println("Overflow indicator: " + (overflow ? 1 : 0)); } }
补充说明
- Java的
int是32位补码,取值范围为-2147483648到2147483647,当累加超出这个范围时会触发循环溢出(例如-2147483648 + (-1)会得到2147483647)。 - 每次累加时即时判断,能覆盖所有负数相加导致的溢出场景,避免仅通过最终结果符号判断的遗漏。
内容的提问来源于stack exchange,提问作者pia zhang
相关产品推荐
相关产品推荐

