【问题标题】:When is (x==(x+y)-y) or (x==(x-y)+y) guaranteed for IEEE floats?何时为 IEEE 浮点数保证 (x==(x+y)-y) 或 (x==(x-y)+y)?
【发布时间】:2019-01-16 11:50:40
【问题描述】:

在 C 或其他使用 IEEE 浮点数的语言中,我有两个变量 xy,它们都保证是有限的、非 NaN 的、基本上是正常的数字。

我有一些代码本质上假定以下代码无效:

float x = get_x ();
float y = get_y ();

float old_x = x;
x += y;
x -= y;
assert (old_x == x);
x -= y;
x += y;
assert (old_x == x);

我知道这对于某些类别的值是正确的,即尾数中没有“很多”有效数字的值,但我想清楚边缘情况。

例如,1.3 的二进制表达式在尾数下一直有有效数字,1.7 也是如此,我不应该完全假设 1.3+1.7==3,但我可以假设如果我添加把这些数字加在一起,然后减去它们,或者反之,我会再次取回第一个值吗?

什么是正式的边缘条件?

【问题讨论】:

  • 很难看出知道这一点的用处,有时它会起作用,而你也知道在许多情况下它不会起作用。
  • 二进制浮点的一个有用的充分条件是 Sterbenz 引理:如果 x/2 ≤ y ≤ 2x,x-y 是精确的(因此,如果 x/2 ≤ −y ≤ 2x,x+y 是确切。)我不记得看到所有确切案例的完整特征。我不认为“边缘”案例是一个很好的描述,因为我怀疑它们会有一些不规则性,例如数量级差异较大的数字比由于低位互补模式而差异较小的某些案例具有准确的结果.

标签: precision numeric ieee-754


【解决方案1】:

浮点流水线中的位数不是标准的一部分。

来自维基百科:

该标准还建议使用扩展格式来执行 内部计算的精度高于所需的精度 最终结果,以尽量减少舍入误差:仅标准 指定此类的最小精度和指数要求 格式。 x87 80 位扩展格式是最常用的 实现了满足这些要求的扩展格式。

因此,由于可以扩展内部格式,不知道何时将内部格式截断为标准格式,使用什么舍入方法,因此无法保证添加一个值然后再次减去它会导致原始值的假设符合标准。

对于您发布的琐碎案例,它可能大部分时间都可以工作。

然后就是处理NAN的情况了。

您可能能够确定您当前使用的架构的边缘情况,但检查当前值是否在原始值的误差范围内可能更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    • 1970-01-01
    相关资源
    最近更新 更多