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)
是否
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.01,则精确值x+x+x将具有最后2位1|1(其中|表示格式中的最后一位),其将向上舍入到0|0.下一个添加将给出精确的结果|01,因此结果将向下舍入,抵消先前的错误.11,则精确值x+x+x将具有最后2位0|1,将向下舍入到0|0.下一个添加将给出一个精确的结果|11,因此结果将向上舍入,再次取消先前的错误.n=5(再次,假设默认舍入):因为x+x+x+x确切,它的原因与之相同n=3.
对于n=6失败,例如取x为1.0000000000000002(下一个double后1.0),在这种情况下6x是6.000000000000002与x+x+x+x+x+x是6.000000000000001