确定乘法输出是否符合64位的最大值

determine if multiplication output fits into max value of 64 bits

本文关键字:64位 最大值 是否 输出      更新时间:2023-10-16

我有一个乘法行,它可以产生大于64位的输出值。(我最多能hold住)。

我想确定确定输出是否大于64位的最佳方法是什么

我已经尝试了一些事情,比如。

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

变量初始化为一些值

两个任意大小的无符号整数(!)的乘法a * b,我们称其为T,当且仅当结果大于T所能容纳的最大数字时将溢出。标准库可以使用std::numeric_limits访问任何类型T的最大数量。

上面的语句也可以写成:当且仅当a > max(T) / bb > max(T) / a相同(其中/是整数除法,max(T)T所能容纳的最大数),a * b会溢出

例子:我们说T = uint8_t,所以max(T) == 255。下面是几个演示示例:

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

使用此方法检查乘法a * b是否会溢出:

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

然后,对三个数的乘积使用此方法两次:

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;
另一种选择是将乘法和检入封装为一个方法。如果发生溢出,则抛出异常
template<typename T>
T safeMultiplication(T a, T b) {
    if (a > std::numeric_limits<T>::max() / b)
        throw ...;
    else
        return a * b;
}

您可以将此行为封装在自定义类型中,该类型重载算术运算符并在发生溢出时抛出。

如果你认为溢出是"正常行为"/在"正常情况下",不要使用异常。在这种情况下,请在自定义类型中使用错误参数/标志。

NaN异常状态下的浮点算术中也有类似的事情:用NaN值继续计算将再次得到NaN。在自定义类型中标记溢出的类似实现将确保您可以轻松地检测链式计算中的溢出,例如三个数字的乘积。自定义类型的关键在于,您不必编写要计算的表达式两次:作为计算本身加上预先的溢出检查。