2016-03-27 7 views
2

Ich habe eine Tabelle mit 1000er x- und y-Koordinaten. Welches ist der schnellste Weg, um eine passende Funktionsgleichung zu finden?Finde die Funktionsgleichung aus der Wertetabelle

Die Tabelle sieht wie folgt aus:

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 für die Zeit steht, y für die Amplitude.

Ich möchte jetzt eine Gleichung erstellen, die alle diese Punkte y zu einer bestimmten Zeit t trifft. Der Übergang von einem y zum anderen sollte so glatt (linear?) Wie möglich sein, auch keine geraden Linien. Ich möchte, dass es in einer Art Wellenform wie eine asynchrone Sinuswelle ist.

Weiß jemand, wie man das erreicht?

+0

Blick in Regression nimmt zu. – intboolstring

+1

Obwohl es eher wie ein Matlab-Job als Java klingt, hier ist ein [kubischer Spline] (https://commons.apache.org/proper/common-math/jacoco/org.apache.commons.math3.analysis.interpolation/SplineInterpolator .java.html Quellcode. – Daniel

Antwort

0

Sie können kubische Splines verwenden, um kubische Segmente zwischen jedem Punktpaar zu erstellen. Der Spline stellt sicher, dass Sie alle Punkte treffen und die Stetigkeit zwischen den Segmenten höher als 0 ist. Eine Stetigkeit von 0 bedeutet, dass Linien verwendet werden, um die Punkte zu verbinden. Unten ist eine Implementierung eines Catmull-Rom Spline, der einer der einfachsten/coolsten Splines da draußen ist.
Caveat
Diese Implementierung übernimmt x monoton

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