Java 对一个(或两个)数组进行插值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1221944/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Interpolation over an array (or two)
提问by Robert
I'm looking for a java library or some help to write my own interpolation function. That is I have two arrays of doubles which are potentially different sizes, but are ordered. I need to be able to make an estimate of intermediate values, and insert so that both arrays become the same size. In fact the total number of points appearing in the interpolation is the sum of the 2 array sizes minus 1. The range of each array must stay the same however, so there is no extrapolation needed.
我正在寻找一个 java 库或一些帮助来编写我自己的插值函数。也就是说,我有两个双精度数组,它们的大小可能不同,但已排序。我需要能够估计中间值,并插入以使两个数组的大小相同。事实上,出现在插值中的点总数是 2 个数组大小的总和减去 1。然而,每个数组的范围必须保持不变,因此不需要外推。
eg. a1 = [1, 4, 9, 16, 25, 36] and a2 = [6, 9, 14, 30]
例如。a1 = [1, 4, 9, 16, 25, 36] 和 a2 = [6, 9, 14, 30]
the results could be eg.
结果可能是例如。
a1 = [1, 2.25, 4, 6.25, 9, 12.25, 16, 25, 36] and a2 = [6, 6.5625, 7.25, 9, 10.0625, 11.25, 14, 25.25, 30]
a1 = [1, 2.25, 4, 6.25, 9, 12.25, 16, 25, 36] 和 a2 = [6, 6.5625, 7.25, 9, 10.0625, 11.25, 14, 25.25, 30]
these examples are f(x) = x^2 and g(x) = x^2 + 5
, however could easily have been any polynomial - the point is to be able to estimate/approximate the function from the dataset well enough to provide decent enough interpolation. Here the x value is just the index of the input array. In the output only the y values are important.
这些例子是f(x) = x^2 and g(x) = x^2 + 5
,但是很容易是任何多项式 - 关键是能够从数据集中估计/近似函数足够好,以提供足够好的插值。这里 x 值只是输入数组的索引。在输出中,只有 y 值很重要。
采纳答案by BobMcGee
The other answers give you linear interpolations -- these don't really work for complex, nonlinear data. You want a spline fit, (spline interpolation) I believe.
其他答案为您提供线性插值——这些对复杂的非线性数据并不真正有效。 你想要一个样条拟合,(样条插值)我相信。
Spline fits describe regions of the data using a set of control points from the data, then apply a polynomial interpolation between control points. More control points gives you a more accurate fit, less a more general fit. Splines are much more accurate than linear fits, faster to use than a general regression fit, better than a high-order polynomial because it won't do crazy things between control points.
样条拟合使用来自数据的一组控制点描述数据区域,然后在控制点之间应用多项式插值。更多的控制点为您提供更准确的拟合,而不是更一般的拟合。样条比线性拟合准确得多,使用速度比一般回归拟合快,比高阶多项式更好,因为它不会在控制点之间做疯狂的事情。
I can't remember names off the top of my head, but there are some excellent fitting libraries in Java -- I suggest you look for one rather than writing your own function.
我一时想不起来名字,但在 Java 中有一些优秀的拟合库——我建议你寻找一个而不是编写自己的函数。
**EDIT: Libraries that might be useful: **
**编辑:可能有用的库:**
- JMSL
- JSpline+
- Curfitting library(hope you can read German)
** Theory/code that may be useful: **
** 可能有用的理论/代码:**
回答by KitsuneYMG
Simple linear interpolation can be calculated using something like:
可以使用以下方法计算简单的线性插值:
Point2D interp1_lin(Point2D p1, Point2D p2, double x) {
//Pre conditions
assert p1.x<x;
assert x<p2.x;
//Calculate slope from p1 to p2
double m = (p2.x-p1.x)/(p2.y-p1.y);
//Calculate y position of x
double y = (x-p1.x)*m+p1.y;
//create new point
return new Point2D.Double(x,y);
}
Does this help?
这有帮助吗?
回答by Stroboskop
You need to get the x-values corresponding to the y-values. Otherwise no algorithm will be able to determine whether [1, 16, 81] is x^2 for [1, 4, 9] or x^4 for [1, 2, 3]. Would you interpolate six values or none?
您需要获取与 y 值对应的 x 值。否则,没有算法能够确定 [1, 16, 81] 是 [1, 4, 9] 的 x^2 还是 [1, 2, 3] 的 x^4。你会插入六个值还是没有?
And then, when you're given the x-values, you can use some sort of interpolation (linear, kubic spline, you name it) to approximate the missing values.
然后,当您获得 x 值时,您可以使用某种插值(线性、kubic 样条等)来近似缺失值。
回答by Golgauth
Designed for ONE Dimension data array
专为一维数据数组而设计
import java.util.ArrayList;
public class Interpolator {
public static Float CosineInterpolate(Float y1,Float y2,Float mu)
{
double mu2;
mu2 = (1.0f-Math.cos(mu*Math.PI))/2.0f;
Float f_mu2 = new Float(mu2);
return(y1*(1.0f-f_mu2)+y2*f_mu2);
}
public static Float LinearInterpolate(Float y1,Float y2,Float mu)
{
return(y1*(1-mu)+y2*mu);
}
public static Float[] Interpolate(Float[] a, String mode) {
// Check that have at least the very first and very last values non-null
if (!(a[0] != null && a[a.length-1] != null)) return null;
ArrayList<Integer> non_null_idx = new ArrayList<Integer>();
ArrayList<Integer> steps = new ArrayList<Integer>();
int step_cnt = 0;
for (int i=0; i<a.length; i++)
{
if (a[i] != null)
{
non_null_idx.add(i);
if (step_cnt != 0) {
steps.add(step_cnt);
System.err.println("aDDed step >> " + step_cnt);
}
step_cnt = 0;
}
else
{
step_cnt++;
}
}
Float f_start = null;
Float f_end = null;
Float f_step = null;
Float f_mu = null;
int i = 0;
while (i < a.length - 1) // Don't do anything for the very last element (which should never be null)
{
if (a[i] != null && non_null_idx.size() > 1 && steps.size() > 0)
{
f_start = a[non_null_idx.get(0)];
f_end = a[non_null_idx.get(1)];
f_step = new Float(1.0) / new Float(steps.get(0) + 1);
f_mu = f_step;
non_null_idx.remove(0);
steps.remove(0);
}
else if (a[i] == null)
{
if (mode.equalsIgnoreCase("cosine"))
a[i] = CosineInterpolate(f_start, f_end, f_mu);
else
a[i] = LinearInterpolate(f_start, f_end, f_mu);
f_mu += f_step;
}
i++;
}
return a;
}
}
Don't know if it helps... It is very fast coded, so if anyone has a nicer / more performing way to do the same, thank for contributing.
不知道它是否有帮助......它的编码速度非常快,所以如果有人有更好/性能更好的方法来做同样的事情,感谢您的贡献。
USAGE:
用法:
input : Float[] a = {1.0f, null, null, 2.0f, null, null, null, 15.0f};
call : Interpolator.Interpolate(a, "Linear");
output : 1.0|1.3333333|1.6666667|2.0|5.25|8.5|11.75|15.0
回答by Ian Will
I know this is an old answer, but it's the first google hit when searching for Java interpolation. The accepted answer provides some helpful links, but JMSL must be purchased, and the JSpline+ website looks sketchy.
我知道这是一个旧答案,但它是搜索 Java 插值时的第一个谷歌搜索。接受的答案提供了一些有用的链接,但必须购买 JMSL,而且 JSpline+ 网站看起来很粗略。
Apache Commons Math has implementations of linear and spline interpolations that appear simple, functional, and trustworthy.
Apache Commons Math 具有线性和样条插值的实现,它们看起来简单、实用且值得信赖。
回答by Dmide
Light-weight version of one-dimensional array linear interpolator:
一维阵列线性插值器的轻量级版本:
public static float[] interpolate(float[] data) {
int startIdx = -1;
float startValue = 0f;
float element;
for (int i = 0; i < data.length - 1; i++) {
element = data[i];
if (element != 0f) {
if (startIdx != -1) {
doInterpolate(startValue, element, startIdx + 1, i - startIdx - 1, data);
}
startValue = element;
startIdx = i;
}
}
return data;
}
private static void doInterpolate(float start, float end, int startIdx, int count, float[] data) {
float delta = (end - start) / (count + 1);
for (int i = startIdx; i < startIdx + count; i++) {
data[i] = start + delta * (i - startIdx + 1);
}
}
回答by user192127
be very careful with spline-fits and polynomial fits. These two can give nonsensical behavior that can derail many uses of (what is believed to be a representation of) the data.
对样条拟合和多项式拟合要非常小心。这两个可能会产生荒谬的行为,可能会破坏数据的许多用途(被认为是数据的表示)。
Anything that uses derivatives (slopes) of data can be totally derailed.
任何使用数据导数(斜率)的东西都可能完全脱轨。
Best thing you can do is plot the data, understand what it's doing, and only then fit (linear, polynomial, log-log) regression; once you've done that you should plot your fit over the original data and make sure you see reasonable agreement. Skipping this comparison-step is a very bad idea.
你能做的最好的事情是绘制数据,了解它在做什么,然后才拟合(线性、多项式、对数)回归;一旦你完成了,你应该在原始数据上绘制你的拟合并确保你看到合理的一致性。跳过这个比较步骤是一个非常糟糕的主意。
Certain data-sets will not yield to fitting of polynomials, log-log etc..; if your data-points are appropriately distributed over the range of data there's nothing wrong with piecewise-interpolation (linear or polynomial etc.). To beat a dead horse, if you use piecewise interpolation avoid anything that uses derivatives/slopes of your piecewise interpolation because it will have discontinuities and will cause things to behave badly.
某些数据集不会屈服于多项式、log-log 等的拟合;如果您的数据点在数据范围内适当分布,那么分段插值(线性或多项式等)就没有问题。要打败死马,如果您使用分段插值,请避免使用分段插值的导数/斜率的任何内容,因为它会产生不连续性并导致事情表现不佳。
回答by alex
you can use apache commons-mathinterpolation functions, such as SplineInterpolator
您可以使用apache commons-math插值函数,例如SplineInterpolator