Вы можете заранее обнаружить переполнение, разделив максимальное значение, представляемое беззнаковым типом, на одно из множителей; если результат меньше другого множителя, то умножение их приведет к значению, превышающему диапазон беззнакового типа.
Например, в C++ (с использованием числовых типов точной ширины C++0x):
std::uint64_t left = 12;
std::uint64_t right = 42;
if (left != 0 && (std::numeric_limits<std::uint64_t>::max() / left) < right)
{
// multiplication would exceed range of unsigned
}
В C можно использовать uint64_t
для типа и UINT64_MAX
для максимального значения. Или, если вы заботитесь только о том, чтобы тип был по крайней мере шириной 64 бита и не обязательно точно шириной 64 бита,можно использовать unsigned long
и ULLONG_MAX
.
В этом почти дублируемом вопросе есть несколько ответов. Этот ответ должен работать на C, C++ и других подобных языках:
if (b > 0 && a > 18446744073709551615 / b) {
// overflow handling
} else {
c = a * b;
}
Или этот ответ, который выполняет умножение, а затем делит результат на один из аргументов, чтобы увидеть, равен ли он другому:
x = a * b;
if (a != 0 && x / a != b) {
// overflow handling
}
Вероятно, есть более эффективные методы, но это простой и портативный способ сделать это:
// assume 'a' and 'b' are the operands to be multiplied
if( ( a != 0 ) && ( UINT64_MAX / a ) < b ) ) {
// overflow
}