快速查找遭受浮点不准确
Fast lookup suffering from floating point inaccuracies
假设我有等距双精度数(64 位浮点数)x0,x1,...,xn
。等距意味着对于所有的i
,x(i+1) - xi
都是常数;称它为 w
宽度。
给定 [x0,xn]
范围内的数字 y
我想找到最大的 i
使得 xi <= y
.
一种天真的方法会依次访问每个 i
(O(n)
)。稍好一点的是使用二进制搜索 (O(log n)
)。
恒定时间查找将计算 (y-x0)/w
并将其转换为整数。但是,由于浮点不准确,这偶尔会给出错误的结果。例如。假设从 0 开始有 100 个宽度为 0.01 的区间。
(int)(0.29/0.01) = 28 //want 29 here
我能否保留恒定时间查找但确保结果始终与二分查找相同?对 'w' 和 'x0' 使用小数而不是双精度执行计算似乎在这里有效,但它会一直有效吗?我总是可以通过与 x
任一侧的比较来跟踪直接查找,但这看起来很丑陋且效率低下。
澄清一下 - 我得到了 xi
和值 y
作为双打 - 我无法更改它。但是在返回整数索引之前执行的任何中间计算都可以使用我喜欢的任何数据类型。此外,我可以执行一次性 "preparation" 工作以使运行时计算更快。
编辑:抱歉 - 事实证明我没有正确检查 "equally spaced" - 当使用浮点运算计算它们的差异时,这些数字通常不是 "equally spaced"。
执行以下操作
计算(int)(0.29/0.01) = 28 //want 29 here
接下来,计算28-1和28+1之间的i的i * 0.01
,并选择正确的。
你是什么意思equally spaced
?如果可以对数字做出一些假设,例如 - 它们在一个时间间隔内增加,您实际上可以使用中值选择,在最好的情况下为 O(1),在最坏的情况下为 O(log2(N))。
假设我有等距双精度数(64 位浮点数)x0,x1,...,xn
。等距意味着对于所有的i
,x(i+1) - xi
都是常数;称它为 w
宽度。
给定 [x0,xn]
范围内的数字 y
我想找到最大的 i
使得 xi <= y
.
一种天真的方法会依次访问每个 i
(O(n)
)。稍好一点的是使用二进制搜索 (O(log n)
)。
恒定时间查找将计算 (y-x0)/w
并将其转换为整数。但是,由于浮点不准确,这偶尔会给出错误的结果。例如。假设从 0 开始有 100 个宽度为 0.01 的区间。
(int)(0.29/0.01) = 28 //want 29 here
我能否保留恒定时间查找但确保结果始终与二分查找相同?对 'w' 和 'x0' 使用小数而不是双精度执行计算似乎在这里有效,但它会一直有效吗?我总是可以通过与 x
任一侧的比较来跟踪直接查找,但这看起来很丑陋且效率低下。
澄清一下 - 我得到了 xi
和值 y
作为双打 - 我无法更改它。但是在返回整数索引之前执行的任何中间计算都可以使用我喜欢的任何数据类型。此外,我可以执行一次性 "preparation" 工作以使运行时计算更快。
编辑:抱歉 - 事实证明我没有正确检查 "equally spaced" - 当使用浮点运算计算它们的差异时,这些数字通常不是 "equally spaced"。
执行以下操作
计算(int)(0.29/0.01) = 28 //want 29 here
接下来,计算28-1和28+1之间的i的i * 0.01
,并选择正确的。
你是什么意思equally spaced
?如果可以对数字做出一些假设,例如 - 它们在一个时间间隔内增加,您实际上可以使用中值选择,在最好的情况下为 O(1),在最坏的情况下为 O(log2(N))。