IEEE 754浮点加法和乘法的互换性

pla*_*cel 6 c++ floating-point ieee-754 numerical-stability

添加是否x + x可以通过IEEE 754(IEC 559)浮点标准中的乘法2 * x进行互换,或者更一般地说,是否有任何保证并始终给出完全相同的结果?case_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);
}
Run Code Online (Sandbox Code Playgroud)

Sim*_*rne 9

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

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

或者更一般地说,是否有任何保证case_add和case_mul始终给出完全相同的结果?

不一般,没有.从我所知,它似乎适用于n <= 5:

  • n=3:x+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失败,例如取x1.0000000000000002(下一个double1.0),在这种情况下6x6.000000000000002x+x+x+x+x+x6.000000000000001