二进制加法程序处理负数时触发Memory Overflow错误的修正咨询
问题分析
原代码处理负数时失败的核心原因有两个:
- 负数带符号右移导致循环无法终止:Java中
>>是带符号右移,负数右移时高位会补1以保持符号位,比如-1的二进制全为1,每次右移后仍为全1,a永远不会等于0,循环会生成超长二进制字符串,最终Integer.parseInt解析时因超出int范围抛出溢出异常。 - 补码解析逻辑错误:
Integer.parseInt(res.toString(),2)会把二进制字符串当作无符号正数解析,但Java int是32位补码表示,负数的补码字符串会被识别为超大正数,直接超出int取值范围。
修正方案
直接基于int的32位补码特性做位运算,跳过字符串中转环节:
- 固定循环32次:int类型固定为32位,循环32次即可处理完所有有效位,避免负数右移导致的无限循环。
- 直接组装结果位:每计算出一位结果,就将其放到对应位置上,直接返回组装好的int值,从根源避免解析溢出。
- 用
& 0x1确保每次只取最低位参与计算,保证位运算的正确性。
修正后的代码
public int getSum(int a, int b) { int result = 0; int carry = 0; // 循环32次,覆盖int的所有位(包括符号位) for (int i = 0; i < 32; i++) { // 获取a和b的第i位值 int bitA = (a >> i) & 0x1; int bitB = (b >> i) & 0x1; // 计算当前位的结果 int currentBit = bitA ^ bitB ^ carry; // 将当前位设置到结果的对应位置 result |= (currentBit << i); // 更新进位:三种产生进位的情况任意一种成立则进位为1 carry = (bitA & bitB) | (bitA & carry) | (bitB & carry); } return result; }
补充说明
- 循环32次确保处理完int的所有位,负数的补码特性也能被正确识别和计算。
- 通过位运算直接组装结果,完全符合Java int的补码存储规则,不会出现解析溢出问题。
内容的提问来源于stack exchange,提问作者Zephyr
相关产品推荐
相关产品推荐

