2016-03-27 4 views
2

У меня есть таблица с 1000 координатами x и 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 

т обозначает время, у для амплитуды.

Теперь я хочу создать уравнение, которое поражает все эти точки y в определенное время t. Переход от одного y к другому должен быть настолько плавным (линейным?), Насколько это возможно, также нет прямых линий. Я хочу, чтобы он был в форме волны, подобной асинхронной синусовой волне.

Кто-нибудь знает, как это осуществить?

+0

Посмотрите в регрессии. – intboolstring

+1

Хотя это больше похоже на работу с matlab, чем на java, вот [кубический сплайн] (https://commons.apache.org/proper/commons-math/jacoco/org.apache.commons.math3.analysis.interpolation/SplineInterpolator .java.html). – Daniel

ответ

0

Вы можете использовать кубические сплайны для создания кубических сегментов между каждой парой точек. Сплайн гарантирует, что вы ударите все точки, а непрерывность между сегментами будет больше 0. Непрерывность 0 означает, что линии используются для соединения точек. Ниже приведена реализация сплайна Catmull-Rom, который является одним из самых простых/крутых сплайнов.
Caveat
Эта реализация предполагает х монотонно возрастает

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

 Смежные вопросы

  • Нет связанных вопросов^_^