【问题标题】:Retaining maximum possible accuracy on float interpolation保持浮点插值的最大可能精度
【发布时间】:2015-01-12 10:15:13
【问题描述】:

我们知道点 X1 和 X2 有各自的点 Y1 和 Y2,所以我们可以计算任意 X 的 Y:

 X - X1    Y - Y1
------- = -------
X2 - X1   Y2 - Y1

我们可以从中得到简单的公式(A):

Y = (X - X1) * (Y2 - Y1) / (X2 - X1) + Y1;

这在数学上应该是等价的 (B):

Y = (X - X1) / (X2 - X1) * (Y2 - Y1) + Y1;

对于整数数学公式 A,只要乘法 (X - X1) * (Y2 - Y1) 结果保持在类型范围内,A 的性能就会更好。公式 B 不起作用,因为如果 X1 <= X <= X2,那么除法将始终等于 0。

对于浮点,两者都应该工作,但我认为 B 会提供更好的准确性,因为乘法结果会保持较小。

  1. 我对浮点精度的假设是否正确?

  2. 是否有一些我没有考虑到的浮点怪癖?

假设 IEEE 754 浮点表示。

注意 1:我对浮点大小写感兴趣,整数数学非常简单。

注意2:FP公式上的变量可能有非整数值,但NaN和Infs不在问题范围内。

【问题讨论】:

  • 请说明:您对具有浮点值还是仅整数值的点感兴趣?

标签: c floating-point interpolation


【解决方案1】:

为Y解决以下问题

 X - X1    Y - Y1
------- = -------
X2 - X1   Y2 - Y1

(A) 和 (B) 都会表现出相似性:

(A)    Y = (X - offsetX) * deltaY / deltaX + offsetY;
(B)    Y = (X - offsetX) / deltaX * deltaY + offsetY;

如果点最初是整数,“B ...乘法结果将保持较小。”可能成立,但其他方面 |deltaX| |deltaY| 可能都小于 1,然后这个假设可能会失败。

要提高准确性,请考虑减去 2 个数字(或添加 2 个符号不同的相似数字)的效果。代码可以通过反转point1和point2的角色来选择X1,Y1或X2,Y2作为偏移量。 选择最接近 X,Y 的偏移量将提高准确性。

对于 FP 数学,* 和 / 强调 FP 数所允许的指数范围:乘积的精度可以预期在数学上正确答案的位范围内,但范围可能会溢出。

+ 和- 强调精度:范围很少成为问题,但用于形成总和的有效数字可能存在较大的抵消。


如果所有坐标值最初都是整数,建议使用 2 倍宽的整数数学并得出最佳答案。

如果要对最终结果进行整数化,请确保代码使用iy = (int) round(Y);

【讨论】:

    【解决方案2】:

    假设没有发生下溢或上溢,它们在准确性方面应该大致相当:乘法和除法都会产生相同的相对误差,并且由于误差大致是乘法的,因此执行操作的顺序不会有很大的不同。

    如果您对所涉及项的相对大小有所了解,则可以重新排列项以使减法准确,这可能会稍微减少误差。

    【讨论】:

    • 你是说乘法/除法永远不会有问题,但加法/减法会? (当然不包括任何溢出情况)
    • 不仅在某些情况下可以精确地进行减法,例如见docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html中的定理11
    • 还要小心最后的添加:在某些情况下,您可能会遇到灾难性的取消。
    【解决方案3】:

    一般来说,乘法和除法很少会导致显着的精度损失。因为这些是 浮点 数字,具有用于小数位数和有效数字的单独字段,所以获得大的中间结果本身不是问题。 2e100/3e100 和 2/3(出于所有意图和目的)同样准确。

    另一方面,结果量级远小于操作数的加法或减法是导致精度损失的更常见原因。

    考虑到这一点,这两种形式基本上是等价的。如果您的数字是“主流”(即乘法不会导致上溢/下溢),那么您不会遇到任何形式的问题。如果你不能假设你的数字是主流,那么你必须采取各种特殊的预防措施才能获得好的结果。

    现在,与其考虑 (A) 和 (B) 两种形式,我建议在 (A) 和 (C) 之间进行选择:

    Y = (X - X1) * (Y2 - Y1) / (X2 - X1) + Y1; (A)
    Y = (X - X2) * (Y2 - Y1) / (X2 - X1) + Y2; (C)
    

    并选择第一个因素X - X1 或X - X2 的量级较小的形式。这样一来,如果 Y 变小,您可以最大限度地减少精度损失。

    例如,让我们使用

    (X1,Y1) = (-100, -100)
    (X2,Y2) = (0, 0)
    X = 0.76
    

    三位数的精度。然后我们得到(A):

    Y = (0.76 - -100) * (0 - -100) / (0 - -100) + -100
      = 101 * 100 / 100 - 100
      = 1
    

    而对于 (C),我们得到:

    Y = (0.76 - 0) * (0 - -100) / (0 - -100) + 0
      = 0.76 * 100 / 100 + 0
      = 0.76
    

    所以,您的问题的快速答案是:

    1. 中间结果的大小本身并不重要。这不是更喜欢(B)而不是(A)的理由。

    2. 始终将加法和减法视为更可能导致精度损失的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      • 2011-05-17
      • 2013-05-26
      • 1970-01-01
      • 1970-01-01
      • 2017-01-19
      相关资源
      最近更新 更多