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

时间:2016-10-04 15:07:18

标签: c++ floating-point ieee-754 numerical-stability

加法x + x是否可以通过 IEEE 754(IEC 559)浮点标准中的乘法2 * x进行互换,或者更一般地说是case_add可以保证case_mul 1}}和#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 application specific configuration scripts"
- include: "app_cfg/{{ app_name }}.yml"
  when: "{{ app_conf[app_name].app_cfg }}"
  ignore_errors: no
  tags:
    - conf

4 个答案:

答案 0 :(得分:9)

  

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

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

  

或更一般地说,是否保证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的确切值将具有1|1的最后2位(其中|表示格式中的最后一位),这将是被舍入到0|0。下一个添加将给出一个精确的结果|01,因此结果将向下舍入,取消之前的错误。
    • 如果最后2位为11,则x+x+x的确切值将包含0|1的最后2位,其将向下舍入为0|0。下一个添加将给出精确结果|11,因此结果将向上舍入,再次取消之前的错误。
  • n=5(同样,假设默认舍入):由于x+x+x+x是准确的,因此与n=3的原因相同。

对于n=6,它失败了,例如取x1.0000000000000002double之后的下一个1.0),在这种情况下,6x6.000000000000002x+x+x+x+x+x6.000000000000001

答案 1 :(得分:3)

如果n例如pow(2, 54),那么乘法就可以了,但是在结果值远大于输入x时,在加法路径中,{{1}将产生result += x

答案 2 :(得分:1)

是的,但它并不普遍。乘以高于2的数字可能不会给出相同的结果,因为您更改了指数,如果替换为adds,则可能会略微下降。但是,如果由添加操作替换,则乘以2不会丢失一点。

答案 3 :(得分:1)

如果result中的累加器case_add变得太大,添加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