我正在进行一些浮点计算,结果并不像我希望的那样准确。
这是算法:
... center = (max_x + min_x) / 2 distance = old_x - center new_x = center + (distance * factor) return new_x
min_x,max_x和old_x都是浮点数。 我相信当我取最大值和最小值的平均值时会引入最大误差,然后将误差乘以因子(可以是浮点数)。
如何最小化FP计算引起的错误,以便new_x尽可能精确?
答案 0 :(得分:4)
如果 old_x 且中心已关闭,那么您将失去精确度。
您可以更改计算,以便最后发生减法:
center = (max_x + min_x) / 2
new_x = (center + (old_x * factor)) - (center * factor)
答案 1 :(得分:2)
根据您的语言,您可以使用固定/任意精确数字类型,例如decimal in python或BigDecimal in Java。
答案 2 :(得分: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_x
和max_x
之间的关系有更多了解,那么您可能会做得更好。
答案 3 :(得分:1)
正如Yochai所说,你的问题可能是由减法old_x - center
引起的。如果old_x
和center
彼此接近,那么您将失去精确度。
简单的解决方案是使用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
和center
相距很远而max_x
和min_x
的平均值接近center
,则会有所帮助。如果这没有帮助,也许您可以调整max_x
的计算,以便您实际计算max_x - center
但需要更改您未向我们展示的部分。
答案 4 :(得分: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
如果因子也是一个固定点(整数),N位描述分数,则new_x可以计算为:
new_x = ( (1 << N) + (center << N) + (distance * factor) ) >> (N + 1)
了解每个部分后,可以压缩上述行:
new_x = ( ((1 + center) << N) + (distance * factor) ) >> (N + 1)
使用的整数类型应该足够大,当然。如果有效范围未知,则应检查此函数的输入和其他内容。在大多数情况下,这不是必需的。
这与定点数学一样好。这就是HW电路执行整数运算的过程。