How do I check if A+B exceed long long? (both A and B is long long) [duplicate]

☆樱花仙子☆ 提交于 2019-11-28 07:26:13
Daniel Fischer

Overflow is possible only when both numbers have the same sign. If both are positive, then you have overflow if mathematically A + B > LLONG_MAX, or equivalently B > LLONG_MAX - A. Since the right hand side is non-negative, the latter condition already implies B > 0. The analogous argument shows that for the negative case, we also need not check the sign of B (thanks to Ben Voigt for pointing out that the sign check on B is unnecessary). Then you can check

if (A > 0) {
    return B > (LLONG_MAX - A);
}
if (A < 0) {
    return B < (LLONG_MIN - A);
}
return false;

to detect overflow. These computations cannot overflow due to the initial checks.

Checking the sign of the result of A + B would work with guaranteed wrap-around semantics of overflowing integer computations. But overflow of signed integers is undefined behaviour, and even on CPUs where wrap-around is the implemented behaviour, the compiler may assume that no undefined behaviour occurs and remove the overflow-check altogether when implemented thus. So the check suggested in the comments to the question is highly unreliable.

Something like the following:

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;

We can reason about this as follows:

  • If A and B are opposite sign, they cannot overflow - the one greater than zero would need to be greater than max or the one less than zero would need to be less than min.

  • In the other cases, simple algebra suffices. A + B > max => B > max - A will overflow if they are both positive. Otherwise if they are both negative, A + B < min => B < min - A.

Mask the signs, cast to unsigned values, and perform the addition. If it's above 1 << (sizeof(int) * 8 - 1) then you have an overflow.

int x, y;
if (sign(x) == sign(y)){
    unsigned int ux = abs(x), uy = abs(y);    
    overflow = ux + uy >= (1 << (sizeof(int) * 8 - 1));
}

Better yet, let's write a template:

template <typename T> 
bool overflow(signed T x, signed T y){
    unsigned T ux = x, uy = y;
    return ( sign(x) == sign(y) && (ux + uy >= (1 << (sizeof(T) * 8 - 1)));
}

Also, if you're only using it for debug, you can use the following 'hack' to read the overflow bit from the last operation directly (assuming your compiler/cpu supports this):

int flags;
_asm {
    pushf       // push flag register on the stack
    pop flags   // read the value from the stack
}
if (flags & 0x0800) // bit 11 - overflow
    ...
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!