0

假设一个有 8 个无符号字符x1,x2,...x8,我们要计算:

abs((x1 + x2 + x3 + x4) - (x5 + x6 + x7 + x8)) / 4

在不引入大的上溢或下溢错误的情况下,确保最准确结果的最佳方法是什么?

我在模板类中使用它,这就是为什么我不能将无符号值转换为有符号值。

4

3 回答 3

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. 如果表达式的结果为负,那么您将进行转换,使值变为正(但定义明确)。

于 2013-12-10T21:15:19.220 回答
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;

您当然可以根据需要调整专业化和添加/删除,但这应该会给您正确的想法。

于 2013-12-10T21:10:27.493 回答
0

与任何固定大小的数据一样,最好的方法是将它们转换为足够大的类型以适应最坏的情况。在这种情况下,将它们强制转换int就足够了——它将适合任何可能值的范围,并允许处理潜在的下溢。

请注意,您必须小心减法 - 结果将取决于您要附加到它的语义:您假设它永远不会下溢(并且任何负值都是错误或应该以 0 为底)或负value 是有意义的,您确实想从中获取绝对值。

于 2013-12-10T21:07:13.653 回答