Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I detect unsigned integer multiply overflow?

I was writing a program in C++ to find all solutions of ab = c, where a, b and c together use all the digits 0-9 exactly once. The program looped over values of a and b, and it ran a digit-counting routine each time on a, b and ab to check if the digits condition was satisfied.

However, spurious solutions can be generated when ab overflows the integer limit. I ended up checking for this using code like:

unsigned long b, c, c_test; ... c_test=c*b;         // Possible overflow if (c_test/b != c) {/* There has been an overflow*/} else c=c_test;      // No overflow 

Is there a better way of testing for overflow? I know that some chips have an internal flag that is set when overflow occurs, but I've never seen it accessed through C or C++.


Beware that signed int overflow is undefined behaviour in C and C++, and thus you have to detect it without actually causing it. For signed int overflow before addition, see Detecting signed overflow in C/C++.

like image 987
Chris Johnson Avatar asked Oct 13 '08 22:10

Chris Johnson


People also ask

How is unsigned overflow detected?

The way you are detecting overflown for a multiplication now is probably the fastest. On ARM as I've commented in HeadGeek's answer you can use the clz instruction or the __clz(unsigned) function to determine the rank of the number (where its highest bit is).

Can unsigned integers overflow?

"A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type."

How do you avoid overflow in multiplication?

We can multiply recursively to overcome the difficulty of overflow. To multiply a*b, first calculate a*b/2 then add it twice. For calculating a*b/2 calculate a*b/4 and so on (similar to log n exponentiation algorithm).


1 Answers

I see you're using unsigned integers. By definition, in C (I don't know about C++), unsigned arithmetic does not overflow ... so, at least for C, your point is moot :)

With signed integers, once there has been overflow, undefined behaviour (UB) has occurred and your program can do anything (for example: render tests inconclusive). 

#include <limits.h>  int a = <something>; int x = <something>; a += x;              /* UB */ if (a < 0) {         /* Unreliable test */   /* ... */ } 

To create a conforming program, you need to test for overflow before generating said overflow. The method can be used with unsigned integers too:

// For addition #include <limits.h>  int a = <something>; int x = <something>; if ((x > 0) && (a > INT_MAX - x)) /* `a + x` would overflow */; if ((x < 0) && (a < INT_MIN - x)) /* `a + x` would underflow */; 

// For subtraction #include <limits.h> int a = <something>; int x = <something>; if ((x < 0) && (a > INT_MAX + x)) /* `a - x` would overflow */; if ((x > 0) && (a < INT_MIN + x)) /* `a - x` would underflow */; 

// For multiplication #include <limits.h>  int a = <something>; int x = <something>; // There may be a need to check for -1 for two's complement machines. // If one number is -1 and another is INT_MIN, multiplying them we get abs(INT_MIN) which is 1 higher than INT_MAX if ((a == -1) && (x == INT_MIN)) /* `a * x` can overflow */ if ((x == -1) && (a == INT_MIN)) /* `a * x` (or `a / x`) can overflow */ // general case if (a > INT_MAX / x) /* `a * x` would overflow */; if ((a < INT_MIN / x)) /* `a * x` would underflow */; 

For division (except for the INT_MIN and -1 special case), there isn't any possibility of going over INT_MIN or INT_MAX.

like image 111
pmg Avatar answered Sep 30 '22 07:09

pmg