如何检查A + B是否超长?(A和B都很长)

abc*_*987 22 c++ long-long

我有2个号码:AB.我需要A+B在代码中的某处计算.这两个ABlong long,并可以积极或消极的.

我的代码运行错误,我怀疑计算时会出现问题A+B.我只想检查是否A+B超出long long范围.因此,任何方法都是可以接受的,因为我只将它用于调试.

Dan*_*her 31

仅当两个数字具有相同符号时才可能溢出.如果两者都是正数,那么无论是数学A + B > LLONG_MAX还是等效,都会溢出B > LLONG_MAX - A.由于右侧是非负的,后一种情况已经暗示B > 0.类似的论点表明,对于否定的情况,我们也不需要检查符号B(感谢Ben Voigt指出签名检查B是不必要的).然后你可以检查

if (A > 0) {
    return B > (LLONG_MAX - A);
}
if (A < 0) {
    return B < (LLONG_MIN - A);
}
return false;
Run Code Online (Sandbox Code Playgroud)

检测溢出.由于初始检查,这些计算不会溢出.

检查结果的符号A + B将有效保证溢出整数计算的环绕语义.但是有符号整数的溢出是未定义的行为,即使在环绕是实现行为的CPU上,编译器也可能认为没有发生未定义的行为,因此在实现时完全删除溢出检查.因此,对问题的评论中建议的检查非常不可靠.

  • @JamesKanze我发现它在单独的情况下更具可读性,但这当然只是我的偏好. (16认同)
  • FWIW,我同意Daniel的风格选择.我不认为if中的返回是"隐藏的",尤其不是7行函数. (10认同)
  • 不仅检查符号不能保证工作,但优化器正在使用缺少保证(例如我刚检查gcc优化`a + 42> a`为'true`). (4认同)

Yuu*_*shi 7

类似于以下内容:

long long max = std::numeric_limits<long long>::max();
long long min = std::numeric_limits<long long>::min();

if(A < 0 && B < 0) 
    return B < min - A;
if(A > 0 && B > 0)
    return B > max - A;

return false;
Run Code Online (Sandbox Code Playgroud)

我们可以这样解释如下:

  • 如果AB符号相反,他们不能溢出-大于零的一个更大的需要是大于max或一个小于零,将需要不到min.

  • 在其他情况下,简单的代数就足够了.A + B > max => B > max - A如果他们都是积极的,他们会溢出 否则,如果他们都是负面的,A + B < min => B < min - A.