检查java中长时间运行的进位

时间:2014-06-20 16:19:31

标签: java

添加/减去两个long类型的数字。有没有办法弄清楚这个操作是否会设置理论进位?

2 个答案:

答案 0 :(得分:3)

这应该做:

/**
 * 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;
}

此前已经提到过这个问题:How does Java handle integer underflows and overflows and how would you check for it?(此处也有减法描述)

编辑:由于不清楚OP是否意味着无符号加法,因此也不难发现。如果重新考虑问题为“如果我们有两个(无符号)64位值并且会添加它们,那么将在结果中设置位64(假设位从0 = LSB到63 =原始操作数中的MSB编号)”< / p>

一点点逻辑思维得出的结论是,如果满足下列条件之一,则会设置第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");

答案 1 :(得分:1)

来自Java语言规范(Java SE 8)整数运算符不以任何方式表示溢出或下溢。所以你必须自己测试一下:

  • 两个正数和负数的总和=&gt;溢出
  • 两个负数和正结果之和=&gt;下溢
  • 正面和负面之和既不会溢出也不会下溢
  • sub的规则:a - b = a +( - b)

只要您在数字之间的每次操作中进行测试,就可以了。