我有一个乘法线,可能导致输出大于64位的值。 (我能忍住)。
我想确定什么是确定输出是否大于64位的最佳方法。
我尝试了一些类似的东西。
uint64_t val1, val2, val3;
if ((val1 * val2 * val3 ) > UINT64_MAX) {
//warning message
}
else {
//do something
}
将变量初始化为某些值。
答案 0 :(得分:4)
当且仅当结果大于最大数{{1 }} 能把持住。标准库可以使用std::numeric_limits
访问任意类型a * b
的最大数量。
以上陈述也可以写成:T
当且仅当T
与T
相同时才会溢出(其中a * b
是整数除法a > max(T) / b
是b > max(T) / a
可以容纳的最大数量。
示例:我们说/
,所以max(T)
。几个示例示例:
T
使用此方法检查乘法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;
}
。在自定义类型中标记溢出的类似实现将确保您可以轻松地检测链式计算中的溢出,例如三个数字的乘积。关于自定义类型的要点是您不必编写要计算两次的表达式:作为计算本身加上预先进行的溢出检查。