这应该做:
/**
* Add two long's with overflow detection (r = s + d)
*/
public static long add(final long s, final long d){
final long r = s + d;
if (((s & d & ~r) | (~s & ~d & r)) < 0)
throw new RuntimeException("long overflow add(" + s + ", " + d + ")");
return r;
}
之前已经在这里问过这个问题:Java 如何处理整数下溢和溢出以及如何检查它? https://stackoverflow.com/questions/3001836(那里也描述了减法)
编辑:由于不清楚 OP 是否意味着无符号加法,因此也不太难检测。如果我们重新思考这个问题,“如果我们有两个(无符号)64 位值并将它们相加,结果中是否会设置第 64 位(假设原始操作数中的位编号从 0=LSB 到 63=MSB)”
稍加逻辑思考即可得出这样的结论:如果以下多个条件为真,则将设置第 64 位:
- 操作数 1 的位 63 被设置
- 操作数 2 的位 63 被设置
- 两个操作数的低位 (0-62) 之和产生到位 63 的进位
这很容易检查:
long operand1 = ...
long operand2 = ...
long bitMask = Long.MAX_VALUE; // bits 0-62 set, bit 63 clear
int conditions = 0;
if (operand1 < 0)
++conditions;
if (operand2 < 0)
++conditions;
if (((operand1 & bitMask) + (operand2 & bitMask)) < 0)
++conditions;
if (conditions > 1)
System.out.println("carry would be set!");
我没有花任何时间思考如何优化,我确信有一个更简洁的解决方案。
对于无符号减法,它非常简单:如果 b 大于 a,则在 (a - b) 中发生借位。这可以通过无符号比较来检查,可以用 java 表示为:
long flipSignBit = Long.MIN_VALUE; // only bit 63 set, others clear
if ((a ^ flipSignBit) < (b ^ flipSignBit))
System.out.println("borrow occurs");