6

IEEE 754(IEC 559)浮点标准中的乘法是否x + x可以互换加法,或者更一般地说,是否有任何保证并且总是给出完全相同的结果?2 * xcase_addcase_mul

#include <limits>

template <typename T>
T case_add(T x, size_t n)
{
    static_assert(std::numeric_limits<T>::is_iec559, "invalid type");

    T result(x);

    for (size_t i = 1; i < n; ++i)
    {
        result += x;
    }

    return result;
}

template <typename T>
T case_mul(T x, size_t n)
{
    static_assert(std::numeric_limits<T>::is_iec559, "invalid type");

    return x * static_cast<T>(n);
}
4

4 回答 4

9

IEEE 754 (IEC 559) 浮点标准中的加法是否x + x可以通过乘法互换2 * x

是的,因为它们在数学上是相同的,所以它们会给出相同的结果(因为结果是精确的浮点数)。

或更一般地说,是否可以保证 case_add 和 case_mul 总是给出完全相同的结果?

一般不会,不会。据我所知,它似乎适用于n <= 5

  • n=3x+x准确无误(即不涉及四舍五入),因此(x+x)+x在最后一步只涉及一次四舍五入。
  • n=4(并且您使用的是默认舍入模式)然后

    • 如果 的最后一位x是 0,那么x+x+x是精确的,因此结果与 相同的参数相等n=3
    • 如果最后 2 位是01,则 的确切值x+x+x将具有最后 2 位1|1(其中 | 表示格式中的最后一位),将四舍五入为0|0. 下一个加法会给出一个精确的结果|01,所以结果会被四舍五入,抵消之前的错误。
    • 如果最后 2 位是11,则 的确切值x+x+x将具有 的最后 2 位0|1,将向下舍入为0|0。下一个加法将给出一个精确的结果|11,所以结果将被四舍五入,再次抵消前一个错误。
  • n=5(再次,假设默认舍入):因为x+x+x+x是精确的,它的成立原因与n=3.

因为n=6它失败了,例如 take xto be 1.0000000000000002(下一个doubleafter 1.0),在这种情况下6xis6.000000000000002x+x+x+x+x+xis6.000000000000001

于 2016-10-04T15:55:10.887 回答
3

n例如,如果是,pow(2, 54)那么乘法就可以正常工作,但是在加法路径中,一旦结果值足够大于输入xresult += x就会产生result

于 2016-10-04T15:18:39.500 回答
1

是的,但一般不成立。乘以大于 2 的数字可能不会得到相同的结果,因为您已经更改了指数,如果用加法替换,可能会下降一点。但是,如果用加法运算代替,乘以 2 就不会下降一点。

于 2016-10-04T15:27:50.607 回答
1

如果累加器resultincase_add变得太大,相加x将引入舍入误差。在某一点上,添加x根本没有效果。所以函数不会给出相同的结果。

例如,如果double x = 0x1.0000000000001p0(十六进制浮点表示法):

n  case_add              case_mul

1  0x1.0000000000001p+0  0x1.0000000000001p+0
2  0x1.0000000000001p+1  0x1.0000000000001p+1
3  0x1.8000000000002p+1  0x1.8000000000002p+1
4  0x1.0000000000001p+2  0x1.0000000000001p+2
5  0x1.4000000000001p+2  0x1.4000000000001p+2
6  0x1.8000000000001p+2  0x1.8000000000002p+2
于 2016-10-04T15:32:09.560 回答