4

I have a multiplication line that can result in output greater than 64 bit values. (max i can hold).

I want to determine what is the best way to determine if the output is greater than 64 bits.

I have tried some things like.

uint64_t val1, val2, val3;
if ((val1 * val2 * val3 ) > UINT64_MAX) {
    //warning message
}
else {
    //do something
}

variables are initialized to some values.

Dexter
  • 1,299
  • 3
  • 20
  • 38
  • 2
    you can read the answers to this question: http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-c-c –  Apr 05 '13 at 10:06
  • see also http://stackoverflow.com/questions/8534107/detecting-multiplication-of-uint64-t-integers-overflow-with-c – salva Apr 05 '13 at 11:00

1 Answers1

4

A multiplication a * b of two unsigned (!) integer numbers of arbitrary size, let's call this type T, will overflow if and only if the result would be greater than the maximum number T can hold. The standard library can access the maximum number of any type T using std::numeric_limits.

The above statement can also be written as: a * b will overflow if and only if a > max(T) / b, which is the same as b > max(T) / a (where / is an integer division and max(T) is the maximum number T can hold).

Example: Let's say T = uint8_t, so max(T) == 255. A couple of examples for demonstration:

a              |  16 |  15 |  14
b              |  16 |  17 |  18
---------------------------------
a * b          | 256 | 255 | 252
overflow?      | yes |  no |  no
---------------------------------
max(T)/b       |  15 |  15 |  14
a > max(T)/b?  | yes |  no |  no

Use this method to check if a multiplication a * b will overflow:

#include <limits.h>

template<typename T>
bool multiplicationWillOverflow(T a, T b) {
    return a > std::numeric_limits<T>::max() / b;
}

Then, use this method twice on your product of three numbers:

uint64_t val1, val2, val3;
if (multiplicationWillOverflow(val1, val2)) {
    //warning message
}

uint64_t product12 = val1 * val2, 
else if (multiplicationWillOverflow(product12, val3)) {
    //warning message
}

uint64_t product123 = product12 * val3;

Another option is to encapsulate the multiplication and the check in one method. Throw an exception if an overflow occurs.

template<typename T>
T safeMultiplication(T a, T b) {
    if (a > std::numeric_limits<T>::max() / b)
        throw ...;
    else
        return a * b;
}

You can encapsulate this behavior in a custom type, which overloads arithmetic operators and throws if an overflow would happen.

Don't use exceptions if you expect overflows as "normal behavior" / under "normal circumstances". In such cases, use an error parameter / a flag in a custom type instead.

A similar thing is done in floating point arithmetic with NaN exceptional states: Continuing a calculation with a NaN value will result in NaN again. A similar implementation for flagging overflow in your custom type will make sure you can detect overflow in chained calculations, like your product of three numbers, easily. The point about a custom type is that you don't have to write the expression to be calculated twice: As the calculation itself plus the overflow checking in advance.

leemes
  • 44,967
  • 21
  • 135
  • 183