从值表中查找函数方程

时间:2016-03-27 17:49:45

标签: java equation equation-solving

我有一张包含1000和x坐标和y坐标的表格。找到匹配函数方程的最快方法是什么?

表格如下:

t - y

0 - 0.3113
1 - 0.5493
2 - 0.7190
3 - 0.6474
4 - 0.9200
5 - 0.2467
6 - 0.8068
7 - 0.5910
8 - 0.8302
9 - 0.2612
10 - 0.9869

t代表时间,y代表振幅。

我现在想要创建一个方程式,在某个时间t点击所有这些点y。从一个y到另一个的过渡应该是如此平滑(线性?),也没有直线。我希望它是一种像异步正弦波一样的波形。

有人知道如何做到这一点吗?

1 个答案:

答案 0 :(得分:0)

您可以使用三次样条线在每对点之间创建立方体段。样条曲线将确保您点击所有点并且段之间的连续性高于0.连续性0表示使用线来连接点。下面是Catmull-Rom样条曲线的实现,它是最简单/最酷的样条曲线之一。
买者
该实现假设x是单调递增的

import java.util.Arrays;

public class CatmullRomSpline
{
    protected double[] _x;
    protected double[] _y;
    public CatmullRomSpline(final double[] x, final double[] y) 
    {
        this._x = x;
        this._y = y;    
    }

    public double getValueAt(double x) 
    {
        int length = this._x.length;
        int index = Arrays.binarySearch(this._x, x);
        double result;
        // Exact match was found
        if(index >= 0)
        {
            result = this._y[index];
        }
        // x is smaller than the smaller value in the sequence
        else if(index == -1)
        {
            result = -1;
        }
        // x is larger than the largest number in the sequence
        else if(index == -length - 1)
        {
            result = -2;
        }
        // the number is between two of the numbers in the sequence
        else
        {
            index = -(index + 2);
            double p0, p1, p2, p3;
            if(index == 0)
            {
                p1 = this._y[0];
                p2 = this._y[1];
                p3 = this._y[2];
                p0 = 2 * p1 - p2;   
            }
            else if(index >= length - 2)
            {
                p0 = this._y[length - 3];
                p1 = this._y[length - 2];
                p2 = this._y[length - 1];
                p3 = 2 * p2 - p1;
            }
            else
            {
                p1 = this._y[index];
                p2 = this._y[index + 1];
                p3 = this._y[index + 2];
                p0 = this._y[index - 1];
            }
            // Normalize range from [0, 1] to agree with the derivation of the spline 
            x = (x - this._x[index]) / (this._x[index + 1] - this._x[index]);
            double c0 = p1;
            double c1 = p2 - p0;
            double c2 =  p2 - p1;
            double c3 = p1 - p3;
            double c4 = c1 - c3;
            result = c0 + x * (0.5 * c1 + x * (0.5 * c3 + 3 * c2 - c1 + x * (0.5 * c4 - 2 * c2)));
        }
        return result;
    }
    public static void main(String[] args)
    {
        // I'm fitting a parabola from t = 1 to t = 4
        double[] t = new double[] {0, 1, 2, 3, 4, 5};
        double[] y = new double[] {0, 1, 4, 9, 16, 25};

        int noPoints = 6;
        double[] tHat = linspace(1.0, 4.0, noPoints);

        CatmullRomSpline csp = new CatmullRomSpline(t, y);
        for(double value : tHat)
        {
            System.out.printf("y(t = %.4f) = %.4f\n", value, csp.getValueAt(value));
        }
        /* Output
            y(t = 1.0000) = 1.0000
            y(t = 1.5000) = 2.2500
            y(t = 2.0000) = 4.0000
            y(t = 2.5000) = 6.2500
            y(t = 3.0000) = 9.0000
            y(t = 3.5000) = 12.2500
            y(t = 4.0000) = 16.0000
        */
    }
    public static double[] linspace(double begin, double end, int noPoints)
    {
        double[] arr = new double[noPoints + 1];
        double delta = (end - begin) / noPoints;
        for(int i = 0; i < noPoints; i++)
        {
            arr[i] = begin + i * delta;
        }
        arr[noPoints] = end;
        return arr;
    }
}