Java多项式函数拟合的实现方法

介绍

项目中遇到给出几个间隔时间点的数据,然后判断其他时刻的数据,需要整体考虑数据的变化趋势,不能通过插值来得到中间未知时刻的数据,所以需要使用多项式拟合来将数据补全。

多项式函数是一个很重要的建模手段,利用任意个点,就可以拟合出一个多项式函数,通过多项式函数来推导出其他点的函数值,然后绘制出函数曲线,这个是最基本的原理!

拟合方法

  1. 通过点来拟合,得到拟合多项式的函数关系;
  2. 将得到的集合关系转化成多项式函数的表达式,形如xxx + axx + b*x +c 的样子;
  3. 将多项式函数表达式,解析成一个计算方法;
  4. 通过计算方法,来得到任意x(横坐标)对应的y(纵坐标)的值。

下面是用Java语言来实现多项式拟合的代码:

Java实现

拟合功能在下面代码中,已完整实现,可直接使用。

坐标实体类

定义坐标点的类,x(横坐标),y(纵坐标)

package cn.com.em.pu.fitting;

import java.io.Serializable;
import java.util.Objects;

/** * 坐标点 * * @author pupengfei * @version 1.0 * @date 2020/8/27 14:45 */
public class Point implements Serializable { 

    private static final long serialVersionUID = 3256087124347421878L;

    private double x;

    private double y;

    public Point() { 
    }

    public Point(double x, double y) { 
        this.x = x;
        this.y = y;
    }


    public double getX() { 
        return x;
    }

    public void setX(double x) { 
        this.x = x;
    }

    public double getY() { 
        return y;
    }

    public void setY(double y) { 
        this.y = y;
    }

    @Override
    public boolean equals(Object o) { 
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return Double.compare(point.x, x) == 0 &&
                Double.compare(point.y, y) == 0;
    }

    @Override
    public int hashCode() { 
        return Objects.hash(x, y);
    }

    @Override
    public String toString() { 
        return "Point{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}

自定义异常

package cn.com.em.pu.fitting;

/** * 多项式拟合异常 * * @author pupengfei * @version 1.0 * @date 2020/8/27 15:29 */
public class PolynomialFittingException extends Exception { 

    public PolynomialFittingException() { 
    }

    public PolynomialFittingException(String message) { 
        super(message);
    }

    public PolynomialFittingException(String message, Throwable cause) { 
        super(message, cause);
    }
}

多项式计算公式接口

多项式计算公式,只有一个方法,根据x获取y的值

package cn.com.em.pu.fitting;

/** * 多项式计算公式,根据x获取y的值 * * @author pupengfei * @version 1.0 * @date 2020/8/27 13:57 */
@FunctionalInterface
public interface PolynomialFnc { 

    /** * 根据横坐标x,计算纵坐标y的值 * @param x 横坐标 * @return y,纵坐标 */
    double getY(double x);

}

多项式拟合工具类

数据多项式拟合工具类

package cn.com.em.pu.fitting;

import java.util.ArrayList;
import java.util.List;

/** * 数据多项式拟合工具类 * * @author pupengfei * @version 1.0 * @date 2020/8/27 13:56 */
public class PolynomialUtil { 

    /** * 多项式拟合 * @param data 坐标点集合 * @return 多项式计算公式 */
    public static PolynomialFnc fitting(List<Point> data) throws PolynomialFittingException { 
        // 多项式每一项的计算表达式字符串
        List<String> returnResult = new ArrayList<>();

        int n = data.size();

        List<List<Double>> inputMatrix = new ArrayList<>();

        for (int i = 0; i < n; i++) { 
            List<Double> tempArr = new ArrayList<>();
            for (int j = 0; j < n; j++) { 
                tempArr.add(Math.pow(data.get(i).getX(), n - j - 1));
            }

            tempArr.add(data.get(i).getY());
            inputMatrix.add(tempArr);
        }

        for (int i = 0; i < n; i++) { 
            double base = inputMatrix.get(i).get(i);
            for (int j = 0; j < n + 1; j++) { 
                if (base == 0) { 
                    //存在相同x不同y的点,无法使用多项式进行拟合
                    throw new PolynomialFittingException("存在相同x不同y的点,无法使用多项式进行拟合");
                }
                inputMatrix.get(i).set(j, inputMatrix.get(i).get(j) / base);
            }
            for (int j = 0; j < n; j++) { 
                if (i != j) { 
                    double baseInner = inputMatrix.get(j).get(i);
                    for (int k = 0; k < n + 1; k++) { 
                        inputMatrix.get(j).set(k, inputMatrix.get(j).get(k) - baseInner * inputMatrix.get(i).get(k));
                    }
                }
            }
        }
        for (int i = 0; i < n; i++) { 
            if (inputMatrix.get(i).get(n) > 0) { 
                returnResult.add("+");
            }

            if (inputMatrix.get(i).get(n) != 0) { 
                String tmp_x = "";
                for (int j = 0; j < n - 1 - i; j++) { 
                    tmp_x = tmp_x + "*x";
                }
                returnResult.add((inputMatrix.get(i).get(n) + tmp_x));
            }
        }

        // 将多项式表达式,转换为计算公式
        return x -> { 
            double y = 0;
            for (String s : returnResult) { 
                if ("+".equals(s)) { 
                    y += 0;
                } else if (s.contains("*")) { 
                    String[] split = s.split("\\*");
                    double temp = 1;
                    for (String s1 : split) { 
                        if ("x".equals(s1)) { 
                            temp *= x;
                        } else { 
                            temp *= Double.parseDouble(s1);
                        }
                    }
                    y += temp;
                } else { 
                    y += Double.parseDouble(s);
                }
            }

            return y;
        };
    }

}

演示代码

package cn.com.em.pu.fitting;

import java.util.ArrayList;
import java.util.List;

/** * 测试 * * @author pupengfei * @version 1.0 * @date 2020/8/27 20:18 */
public class TestExample { 

    public static void main(String[] args) throws PolynomialFittingException { 
        List<Point> data = new ArrayList<>();
        data.add(new Point(1, 1));
        data.add(new Point(2, 2));
        data.add(new Point(3, 2));
        data.add(new Point(4, 1));
        PolynomialFnc fitting = PolynomialUtil.fitting(data);
        System.out.println(fitting.getY(3));

        data = new ArrayList<>();
        data.add(new Point(1, 1));
        data.add(new Point(2, 3));
        fitting = PolynomialUtil.fitting(data);
        System.out.println(fitting.getY(3));
    }

}

Jar包下载

下载地址

    原文作者:leaderFLY
    原文地址: https://blog.csdn.net/leaderFLY/article/details/108268187
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞