浮动插补保留最大可能的精度

时间:2015-01-12 10:15:14

标签: c floating-point interpolation

我们知道点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;

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

对于浮点数,两者都应该有效,但我认为B会提供更好的准确性,因为乘法结果会更小。

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

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

  3. 假设IEEE 754浮点表示。

    注1:我对浮点情况感兴趣,整数数学非常简单。

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

3 个答案:

答案 0 :(得分:3)

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,Y1X2,Y2作为偏移量。 选择最接近X,Y的偏移量将提高准确度

使用FP数学,*/强调FP编号允许的指数范围:产品的精度可以在数学上正确的答案范围内,但范围可能溢出。

+-强调精度:范围很少是一个问题,但用于形成总和的有效数字可能会有很大的取消。


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

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

答案 1 :(得分:2)

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

如果你对所涉及的术语的相对大小有所了解,你可能可以重新排列术语,使得减法是精确的,这可能会略微减少误差。

答案 2 :(得分:1)

通常,乘法和除法很少会导致精度的显着下降。因为这些是浮点数字,对于比例和有效数字具有单独的字段,所以获得大的中间结果本身并不是问题。 2e100/3e1002/3(出于所有意图和目的)同样准确。

另一方面,加法或减法的结果比操作数小得多,这是导致精度损失的常见原因。

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

现在,我建议在(A)和(C)之间选择,而不是考虑两种形式(A)和(B):

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

并选择第一个因素X - X1X - 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. 始终认为加法和减法更可能是精度损失的原因。