【发布时间】:2016-05-18 20:17:49
【问题描述】:
假设您必须添加一些存储在巨大数组L 中的 32 位定点数,并且您希望获得尽可能准确的结果。此外,除了 L 和 32 位定点数之外,您不得使用任何其他内容(即,您不得将它们转换为 64 位)。对于 L 中的数字之和,您会采取什么方法来获得最准确的结果?
这将是我在 sudo 代码中指出的当前方法:
L = sort(L)
result = 0
lastMax = false -- indicates whether we've extracted the maximum from L last time
while (not empty(L)) and (result not equals +INF or -INF) do:
current = 0
if lastMax:
current = extractMin(L) -- gets and removes minimum from L
else:
current = extractMax(L) -- gets and removes maximum from L
result = safeAdd(result, current)
lastMax = not lastMax
safeAdd(a,b):
if a = +INF: return +INF
else if a = -INF: return -INF
else: return a + b
所以我在从剩余列表 L 中添加最小值/最大值之间交替添加,以便保持在 L 的范围之间。safeAdd 的实现方式表明,一旦我们跨越了准确度范围(即,a+b 的结果产生了 +INF 或 -INF - 就像在 C 中所做的那样)我们将不再更改结果。
您对如何改进该方法有任何建议吗?
旁注:如果我们想要非常精确:我们进一步假设+ 操作可以产生+INF 或-INF,它们可以在编程语言中表示为定点数。但我们假设+INF、-INF 的值不会出现在L 中。而且我们忽略了定点标准也可能有NaN的表示这一事实。
【问题讨论】:
-
你考虑过Kahan summation吗?
-
感谢您的提示!对不起,我只需要将问题从浮点数改为定点数。所以这可能不再相关了。
-
@ndrizza 定点加法只是整数的加法,因此除非存在溢出,否则此操作不会产生错误(即,它是精确的),这是一个稍微不同的问题,可以通过以下方式解决根据用例重新缩放。常用的定点格式不提供无穷大的表示。
-
谢谢,您关于最不重要位的准确性的观点(类似于整数)是正确的。最准确地说,我还意味着避免中间计算中的溢出。让我们暂时离开重新扩展。
-
如果您需要避免 iven 定点格式溢出,并且不想重新缩放,我看到的唯一其他选项是尝试更改操作的顺序,或者选择不同的定点格式(同时为每个定点数保留总共 32 位,例如 S15.16 与 S23.8)。什么是合适的取决于您的用例的具体情况。
标签: addition fixed-point