[英]Interchangeability of IEEE 754 floating-point addition and multiplication
加法x + x
可以通过IEEE 754(IEC 559)浮点标准中的乘法2 * x
x + 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);
}
加法
x + x
可通过IEEE 754(IEC 559)浮点标准中的乘法2 * x
x + x
互换
是的,因为它们在数学上都是相同的,所以它们将给出相同的结果(因为结果在浮点中是精确的)。
或者更一般地说,是否有任何保证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
的精确值将具有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
( 1.0
之后的下一个double
6.000000000000002
),在这种情况下, 6x
为6.000000000000002
, x+x+x+x+x+x
为6.000000000000001
如果n
是例如pow(2, 54)
则乘法将正常工作,但是在加法路径中,一旦结果值足够大于输入x
, result += x
将产生result
。
是的,但它并不普遍。 乘以高于2的数字可能不会给出相同的结果,因为您更改了指数,如果替换为adds,则可能会略微下降。 但是,如果由添加操作替换,乘以2则不会丢失一点。
如果case_add
的累加器result
变得太大,则添加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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.