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包下载

下载地址

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值