数据集的线性插值通常是如何实现的?
How is linear interpolation of data sets usually implemented?
假设给定了一堆 (x,y) 值中的点,并且您需要通过在 x 轴上两个最接近的值之间进行线性插值来生成点,最快的实现方法是什么?
我找了一圈也没找到满意的答案,我觉得是因为我没有找对的词。
例如,如果我得到的是(0,0) (0.5 , 1) (1, 0.5),那么我想得到一个0.7的值;它将是 (0.7-0.5)/(1-0.5) * (0.5-1) + 1;但是什么数据结构可以让我找到 2 个最近的键值来插入它们之间?如果我有很多键值,那么简单的线性搜索/二进制搜索是我能做的最好的吗?
是的,一个简单的二分查找应该很好,通常就足够了。
如果你需要变得更好,你可以尝试interpolation search(与你的值插值无关)。
如果您的点按固定间隔分布(如您的示例,0 0.5 1
),您还可以简单地将值存储在数组中,并通过它们的索引在恒定时间内访问它们。
我通常实现 O(1) 插值的方法是通过一个额外的数据结构,我称之为 IntervalSelector
时间 O(1) 将给出序列的两个周围值进行插值。
一个IntervalSelector
是一个class,当给定一个n
横坐标的sequence
时,它会构建并记住一个table
,它将映射任何给定的值x
到索引 i
使得 sequence[i] <= x < sequence[i+1]
在时间 O(1).
注:以下数组以1为基数
构建 table 的算法过程如下:
- 求
delta
为横坐标输入sequence
中两个连续元素之间的最小距离
- 设置
count := (b-a)/delta + 1
,其中a
和b
分别是第一个和最后一个(升序)sequence
和/
代表整数除法商。
- 定义
table
为 Array
个 count
个元素。
- 对于
1
和 n
之间的 i
,设置 table[(sequence[j]-a)/delta + 1] := j.
- 将在 4 中访问过的
table
的每个条目重复到紧随其后的未访问位置。
在输出时,如果 (j-1)*d <= sequence[i] - a < j*d.
,table
将 j
映射到 i
这是一个例子:
由于元素 3rd 和 4th 是最接近的元素,我们将区间划分为这个最小长度的子区间。现在,我们在 table
中记住了每个 deta-
区间左端的位置。稍后,当给出输入 x
时,我们计算 delta-
此类 x
的区间为 (x-a)/delta + 1
并使用 table 推导出相应的区间序列。如果x
落在第i
个序列元素的左边,我们选择第(i-1)
个。
更准确地说:
给定 a
和 b
之间的任何输入 x
计算 j := (x-a)/delta + 1
和 i := table[j].
如果 x < sequence[i]
放 i := i - 1
。那么,索引i
满足sequence[i] <= x < sequence[i+1]
;否则这两个连续元素之间的距离将小于delta
,这不是
备注:注意如果sequence
中连续元素之间的最小距离delta
太小,table也会有许多条目。我在这里提供的简单描述忽略了这些需要额外工作的病态案例。
假设给定了一堆 (x,y) 值中的点,并且您需要通过在 x 轴上两个最接近的值之间进行线性插值来生成点,最快的实现方法是什么?
我找了一圈也没找到满意的答案,我觉得是因为我没有找对的词。
例如,如果我得到的是(0,0) (0.5 , 1) (1, 0.5),那么我想得到一个0.7的值;它将是 (0.7-0.5)/(1-0.5) * (0.5-1) + 1;但是什么数据结构可以让我找到 2 个最近的键值来插入它们之间?如果我有很多键值,那么简单的线性搜索/二进制搜索是我能做的最好的吗?
是的,一个简单的二分查找应该很好,通常就足够了。
如果你需要变得更好,你可以尝试interpolation search(与你的值插值无关)。
如果您的点按固定间隔分布(如您的示例,0 0.5 1
),您还可以简单地将值存储在数组中,并通过它们的索引在恒定时间内访问它们。
我通常实现 O(1) 插值的方法是通过一个额外的数据结构,我称之为 IntervalSelector
时间 O(1) 将给出序列的两个周围值进行插值。
一个IntervalSelector
是一个class,当给定一个n
横坐标的sequence
时,它会构建并记住一个table
,它将映射任何给定的值x
到索引 i
使得 sequence[i] <= x < sequence[i+1]
在时间 O(1).
注:以下数组以1为基数
构建 table 的算法过程如下:
- 求
delta
为横坐标输入sequence
中两个连续元素之间的最小距离 - 设置
count := (b-a)/delta + 1
,其中a
和b
分别是第一个和最后一个(升序)sequence
和/
代表整数除法商。 - 定义
table
为Array
个count
个元素。 - 对于
1
和n
之间的i
,设置table[(sequence[j]-a)/delta + 1] := j.
- 将在 4 中访问过的
table
的每个条目重复到紧随其后的未访问位置。
在输出时,如果 (j-1)*d <= sequence[i] - a < j*d.
table
将 j
映射到 i
这是一个例子:
由于元素 3rd 和 4th 是最接近的元素,我们将区间划分为这个最小长度的子区间。现在,我们在 table
中记住了每个 deta-
区间左端的位置。稍后,当给出输入 x
时,我们计算 delta-
此类 x
的区间为 (x-a)/delta + 1
并使用 table 推导出相应的区间序列。如果x
落在第i
个序列元素的左边,我们选择第(i-1)
个。
更准确地说:
给定 a
和 b
之间的任何输入 x
计算 j := (x-a)/delta + 1
和 i := table[j].
如果 x < sequence[i]
放 i := i - 1
。那么,索引i
满足sequence[i] <= x < sequence[i+1]
;否则这两个连续元素之间的距离将小于delta
,这不是
备注:注意如果sequence
中连续元素之间的最小距离delta
太小,table也会有许多条目。我在这里提供的简单描述忽略了这些需要额外工作的病态案例。