假设有一个8个无符号字符x1,x2,...x8
,我们想要计算:
abs((x1 + x2 + x3 + x4) - (x5 + x6 + x7 + x8)) / 4
在不引入大量上溢或下溢错误的情况下,确保最准确结果的最佳方法是什么?
我在模板类中使用它,这就是为什么我不能将无符号值转换为有符号值。
答案 0 :(得分:7)
operator +
仅适用于int
及更大版本。因此,当您使用类型为char
的对象(小于int)时,这些值会在操作发生之前自动转换为int。
因此
abs((x1 + x2 + x3 + x4) - (x5 + x6 + x7 + x8)) / 4
由编译器转换为:
abs((static_cast<int>(x1) + static_cast<int>(x2) + static_cast<int>(x3) + static_cast<int>(x4)) -
(static_cast<int>(x5) + static_cast<int>(x6) + static_cast<int>(x7) + static_cast<int>(x8))) / 4
所以除非你加起来很多char,否则你不可能溢出。
将结果分配回unsigned char
时出现问题。如果表达式的结果为负,那么您将获得一个使值为正(但定义良好)的转换。
答案 1 :(得分:1)
您似乎想要一个元函数来告诉您在计算中使用的中间数据类型。
template <class T>
struct arithmetic_type
{
typedef std::int64_t type;
};
template <>
struct arithmetic_type<float>
{
typedef double type;
};
template <>
struct arithmetic_type<double>
{
typedef double type;
};
template <>
struct arithmetic_type<std::uint64_t>
{
typedef std::uint64_t type;
};
typedef typename arithmetic_type<T>::type ar_type;
abs(((ar_type)x1 + x2 + x3 + x4) - ((ar_type)x5 + x6 + x7 + x8)) / 4;
您当然可以调整专业化并根据您的需要添加/删除,但这应该会给您正确的想法。
答案 2 :(得分:0)
与任何固定大小的数据一样,最好的方法是将它们转换为足够大的类型以适应最坏的情况。在这种情况下,将它们转换为int
将足够好 - 它将适合任何可能值的范围,并允许处理潜在的下溢。
请注意,您必须小心减法 - 结果将取决于您要附加到它的语义:要么假设它永远不会下溢(并且任何负值都是错误或者应该被置于0 )或负值有意义,你确实想从中获取绝对值。