在 IEEE 754 (IEC 559) 浮点标准中,加法 x + x
是否可以与乘法 2 * x
互换,或者更一般地说,是否可以保证 case_add
和 case_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);
}
最佳答案
Is the addition
x + x
interchangeable by the multiplication2 * x
in IEEE 754 (IEC 559) floating-point standard
是的,因为它们在数学上是相同的,所以它们会给出相同的结果(因为结果是精确的 float )。
or more generally speaking is there any guarantee that case_add and case_mul always give exactly the same result?
一般不会,不会。据我所知,它似乎适用于 n <= 5
。 :
-
n=3
: 作为x+x
是精确的(即不涉及四舍五入),所以(x+x)+x
只涉及最后一步的一轮舍入。 n=4
(并且您使用的是默认舍入模式)然后- 如果
x
的最后一位为 0,则x+x+x
是精确的,因此结果与n=3
的参数相同. - 如果最后两位是
01
, 然后是x+x+x
的精确值将具有1|1
的最后 2 位(其中 | 表示格式中的最后一位),这将向上取整为0|0
.下一次添加将给出准确的结果|01
,因此结果将向下舍入,抵消之前的错误。 - 如果最后两位是
11
, 然后是x+x+x
的精确值将具有0|1
的最后 2 位, 将向下舍入为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
关于c++ - IEEE 754 浮点加法和乘法的互换性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39855825/