Is the addition x + x
interchangeable by the multiplication 2 * x
in IEEE 754 (IEC 559) floating-point standard , or more generally speaking is there any guarantee that case_add
and case_mul
always give exactly the same result?
#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
Yes, since they are both mathematically identical, they will give the same result (since the result is exact in floating point).
or more generally speaking is there any guarantee that case_add and case_mul always give exactly the same result?
Not generally, no. From what I can tell, it seems to hold for n <= 5
:
n=3
: as x+x
is exact (ie involves no rounding), so (x+x)+x
only involves one rounding at the final step. n=4
(and you're using the default rounding mode) then
x
is 0, then x+x+x
is exact, and so the results are equal by the same argument as n=3
. 01
, then the exact value of x+x+x
will have last 2 bits of 1|1
(where | indicates the final bit in the format), which will be rounded up to 0|0
. The next addition will give an exact result |01
, so the result will be rounded down, cancelling out the previous error. 11
, then the exact value of x+x+x
will have last 2 bits of 0|1
, which will be rounded down to 0|0
. The next addition will give an exact result |11
, so the result will be rounded up, again cancelling out the previous error. n=5
(again, assuming default rounding): since x+x+x+x
is exact, it holds for the same reason as n=3
.
For n=6
it fails, eg take x
to be 1.0000000000000002
(the next double
after 1.0
), in which case 6x
is 6.000000000000002
and x+x+x+x+x+x
is 6.000000000000001
如果n
是例如pow(2, 54)
则乘法将正常工作,但是在加法路径中,一旦结果值足够大于输入x
, result += x
将产生result
。
Yes, but it doesn't hold generally. Multiplication by a number higher than 2 might not give the same results, as you have changed the exponent and can drop a bit if you replace with adds. Multiplication by two can't drop a bit if replaced by add operations, however.
If the accumulator result
in case_add
becomes too large, adding x
will introduce rounding errors. At a certain point, adding x
won't have an effect at all. So the functions won't give the same result.
For example if double x = 0x1.0000000000001p0
(hexadecimal float notation):
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.