对一个(或两个)数组进行插值

发布于 2024-07-30 04:22:25 字数 498 浏览 5 评论 0原文

我正在寻找一个java库或一些帮助来编写我自己的插值函数。 也就是说,我有两个双精度数组,它们的大小可能不同,但已排序。 我需要能够估计中间值,并插入以使两个数组的大小相同。 事实上,插值中出现的总点数是 2 个数组大小之和减 1。但是,每个数组的范围必须保持相同,因此不需要外推。

例如。 a1 = [1, 4, 9, 16, 25, 36] 和 a2 = [6, 9, 14, 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]

这些示例是 f(x) = x^2 和 g(x) = x^2 + 5 ,但是可以很容易地是任何多项式 - 关键是能够足够好地估计/近似数据集中的函数以提供足够好的插值。 这里的 x 值只是输入数组的索引。 在输出中,只有 y 值很重要。

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.

eg. a1 = [1, 4, 9, 16, 25, 36] and 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]

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

骑趴 2024-08-06 04:22:25

使用样条拟合和多项式拟合时要非常小心。 这两者可能会产生无意义的行为,从而破坏数据(被认为是数据的表示)的许多用途。

任何使用数据导数(斜率)的东西都可能完全脱轨。

你能做的最好的事情就是绘制数据,了解它在做什么,然后才拟合(线性、多项式、双对数)回归; 完成后,您应该根据原始数据绘制拟合结果,并确保您看到合理的一致性。 跳过这个比较步骤是一个非常糟糕的主意。

某些数据集不会屈服于多项式、双对数等的拟合; 如果您的数据点在数据范围内适当分布,则分段插值(线性或多项式等)没有任何问题。 为了打败一匹马,如果你使用分段插值,请避免使用分段插值的导数/斜率,因为它会产生不连续性,并导致事情表现不佳。

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.

太傻旳人生 2024-08-06 04:22:25

其他答案为您提供线性插值 - 这些对于复杂的非线性数据实际上不起作用。 你想要一个样条拟合,我相信(样条插值)。

样条拟合使用数据中的一组控制点来描述数据区域,然后在控制点之间应用多项式插值。 控制点越多,配合越准确,控制点越少,配合越普遍。 样条曲线比线性拟合更准确,比一般回归拟合使用起来更快,比高阶多项式更好,因为它不会在控制点之间做疯狂的事情。

我一时记不起名字,但是 Java 中有一些优秀的合适库——我建议您寻找一个而不是编写自己的函数。


**编辑:可能有用的库:**

** 可能有用的理论/代码: **

  • 带代码的样条小程序:链接
  • Arkan 样条线将折线拟合为贝塞尔样条
  • 样条曲线理论,以及一些拟合数学。 如果图书馆不这样做,更多的数学,更少的代码可能会有所帮助。

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.


**EDIT: Libraries that might be useful: **

** Theory/code that may be useful: **

  • Spline applets with code: link
  • Arkan spline fitting for poly-lines to bezier splines
  • Theory of splines, and some math for fitting. More math, less code, might help if the libraries don't.
╄→承喏 2024-08-06 04:22:25

专为一维数据数组设计

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;
}
}

不知道是否有帮助......
它的编码速度非常快,因此如果有人有更好/性能更好的方法来做到这一点,感谢您的贡献。

用法:

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

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
窝囊感情。 2024-08-06 04:22:25

您需要获取与 y 值相对应的 x 值。 否则,没有算法能够确定 [1, 16, 81] 是 [1, 4, 9] 的 x^2 还是 [1, 2, 3] 的 x^4。 您会插入六个值还是不插入?

然后,当给定 x 值时,您可以使用某种插值(线性插值、库比样条插值等)来近似缺失值。

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?

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.

二手情话 2024-08-06 04:22:25

我知道这是一个旧答案,但这是搜索 Java 插值时谷歌的第一个点击。 接受的答案提供了一些有用的链接,但必须购买 JMSL,并且 Jspline+ 网站看起来很粗略。

Apache Commons Math 具有线性和样条插值的实现,看起来简单、实用且值得信赖。

http://commons.apache.org/proper/commons-math/

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.

Apache Commons Math has implementations of linear and spline interpolations that appear simple, functional, and trustworthy.

http://commons.apache.org/proper/commons-math/

三五鸿雁 2024-08-06 04:22:25

可以使用以下方法计算简单的线性插值:

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);
}

这有帮助吗?

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?

┼── 2024-08-06 04:22:25

一维数组线性插值器的轻量级版本:

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);
    }
}

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文