8

我正在做一些浮点计算,结果并不像我希望的那样准确。

这是算法:

...
中心 = (max_x + min_x) / 2
距离 = old_x - 中心
new_x = 中心 + (距离 * 因子)

返回 new_x

min_x、max_x 和 old_x 都是浮点数。我相信当我取最大值和最小值的平均值时会引入最大的误差,然后将误差乘以因子(可以是浮点数)。

我怎样才能最大限度地减少由于 FP 计算导致的错误,以便 new_x 尽可能精确?

4

5 回答 5

4

如果old_xcenter很接近,那么您将失去精度。

这叫做失去意义

您可以更改计算,以便最后发生减法:

center = (max_x + min_x) / 2
new_x = (center + (old_x * factor)) - (center * factor)
于 2011-06-24T17:26:14.803 回答
2

根据您的语言,您可能可以使用固定/任意精度的数字类型,例如python 中的小数Java 中的 BigDecimal

于 2011-06-24T17:25:09.730 回答
1

这至少消除了原始算法中的一个错误来源:

# Adding min and max can produce a value of larger magnitude, losing some low-order bits
center = min_x + (max_x - min_x)/2
distance = old_x - center
new_x = center + (distance * factor)

return new_x

如果您对和之间的关系有更多了解old_x,您可能会做得比这更好。min_xmax_x

于 2011-06-24T22:22:19.250 回答
1

正如 Yochai 所说,您的问题可能是由减法引起的old_x - center。如果old_xcenter彼此接近,那么您将失去精度。

简单的解决方案是使用double而不是进行计算float,但我想这是不可能的。在这种情况下,您需要摆脱减法。一种可能是

distance_max = max_x - center
distance_min = min_x - center
distance = (distance_max + distance_min) / 2
new_x = center + factor * distance

如果max_x和相距甚远,而 和 的平均值min_x接近,这会有所帮助。如果这没有帮助,也许您可​​以调整计算,以便您实际计算,但需要更改您没有向我们展示的部分。centermax_xmin_xcentermax_xmax_x - center

于 2011-06-25T12:36:13.197 回答
1

所有以前的实现都没有使用舍入,因此有很大的错误:以下是在定点数学中如何做到这一点:我使用的是 X.1u 预置(1 LSB 用于小数部分)。

//center = (max_x + min_x) / 2
center = max_x + min_x // zero error here

// distance = old_x - center
distance = (old_x << 1) - center // zero error here

//new_x = center + (distance * factor)
new_x = (**1** + center + (distance * factor)) >> 1

return new_x

如果 factor 也是一个固定点(整数),其中 N 位描述分数,则 new_x 可以计算为:

new_x = ( (1 << N) + (center << N) + (distance * factor) ) >> (N + 1)
  • (center << N)有 N+1 个小数位
  • 距离 * 因子有 N+1 个小数位
  • (1 << N)是“一半”,因为1 << (N+1)在上述定点精度中是“一”。

了解了各个部分之后,就可以将上面的这行代码进行compact了:

new_x = ( ((1 + center) << N) + (distance * factor) ) >> (N + 1)

当然,使用的整数类型应该足够大。如果有效范围未知,则应检查此函数的输入和其他内容。在大多数情况下,这不是必需的。

这和它在定点数学中的表现一样好。这就是硬件电路执行整数数学运算的方式。

于 2013-11-26T08:29:23.410 回答