数值方法 最小二乘法拟合多项式

数值计算方法 专栏收录该内容
16 篇文章 0 订阅

给定数据点(xi ,yi),用最小二乘法拟合数据的多项式,并求平方误差。
xi 0 0.5 0.6 0.7 0.8 0.9 1.0
yi 1 1.75 1.96 2.19 2.44 2.71 3.00

import java.util.Scanner;

public class shujvnihe {
    static final public int N = 20;
    static public double x[] = new double[N];
    static public double y[] = new double[N];
    static public double l[] = new double[N];
    static public double xx[] = new double[N];
    static public double yy[] = new double[N];
    static public double juzhen[][] = new double[N][N + 1];

    static public double e[] = new double[N];

    static public int n;

    static public void display() {
        for (int i = 1; i <= n + 1; i++) {
            for (int j = 1; j <= n + 1 + 1; j++)
                System.out.print(juzhen[i][j] + " ");
            System.out.println();
        }
    }

    static public double x_n(double x, int n) {

        double mul = 1;
        for (int i = 1; i <= n; i++) {
            mul *= x;
        }
        return mul;
    }

    static public double x_y(double y, double x, int n) {

        return y *= x_n(x, n);
    }

    static public void gaosi(int n) {
        //标记列号
        for (int i = 1; i <= n; i++)
            juzhen[0][i] = i;
        juzhen[0][n + 1] = 0;

        //display();

        //消元
        for (int k = 1; k < n; k++) {
            //找绝对值最大的
            double max = Math.abs(juzhen[k][k]);
            int p = k;
            int q = k;
            for (int i = k; i <= n; i++) {
                for (int j = k; j <= n; j++) {
                    if (Math.abs(juzhen[i][j]) > max) {
                        max = Math.abs(juzhen[i][j]);
                        p = i;
                        q = j;
                    }
                }
            }
            //交换行
            for (int i = 1; i <= n + 1; i++) {
                double temp = juzhen[p][i];
                juzhen[p][i] = juzhen[k][i];
                juzhen[k][i] = temp;

            }
            //交换列
            for (int i = 0; i <= n; i++) {
                double temp = juzhen[i][q];
                juzhen[i][q] = juzhen[i][k];
                juzhen[i][k] = temp;
            }

            for (int i = k + 1; i <= n; i++) {
                l[i] = juzhen[i][k] / juzhen[k][k];
                for (int j = 1; j <= k; j++) {
                    juzhen[i][j] = 0;
                }
                for (int j = k + 1; j <= n + 1; j++) {
                    juzhen[i][j] = juzhen[i][j] - l[i] * juzhen[k][j];
                }
                //display();
            }
        }

        //回代
        y[n] = juzhen[n][n + 1] / juzhen[n][n];
        for (int k = n - 1; k >= 1; k--) {
            double sum = 0;

            for (int j = k + 1; j <= n; j++) {
                sum += juzhen[k][j] * y[j];
            }
            y[k] = (juzhen[k][n + 1] - sum) / juzhen[k][k];
        }



        //由y得到x
        for (int i = 1; i <= n; i++) {
            x[(int) juzhen[0][i]] = y[i];
        }
        //输出解
        for (int i = 1; i <= n; i++) {
            System.out.println("a[" + (i - 1) + "]=" + x[i]);
        }
    }

    public static void main(String[] args) {
        //输入
        int m;
        System.out.println("输入点数:");
        Scanner scanner=new Scanner(System.in);
        m = scanner.nextInt();
        System.out.println("输入x,y");
        for (int i = 0; i < m; i++) {
            xx[i] = scanner.nextDouble();
            yy[i] = scanner.nextDouble();
        }
        System.out.println("\"输入拟合次数:\"");
        n = scanner.nextInt();

        //计算矩阵
        juzhen[1][1] = m;

        for (int i = 1; i <= n + 1; i++) {
            for (int j = i; j <= n + 1; j++) {
                double sum1 = 0, sum2 = 0;
                for (int k = 0; k < m; k++) {
                    sum1 += x_n(xx[k], i + j - 2);
                    sum2 += x_y(yy[k], xx[k], i - 1);
                }
                juzhen[i][j] = juzhen[j][i] = sum1;
                juzhen[i][n + 1 + 1] = sum2;
            }
        }
        display();

        //高斯主元素
        gaosi(n + 1);

        //输出拟合多项式
        System.out.println("拟合多项式为:");
        for (int i = 1; i <= n + 1; i++) {
            if (i == 1) {
                System.out.print(x[i]);
                continue;
            }
            if (x[i] > 0)
                System.out.print("+");
            System.out.print(x[i] + "x^" + (i - 1));
        }
        System.out.println();

        //求平方误差
        double esum = 0;
        for (int j = 1; j <= m; j++) {
            for (int i = 1; i <= n + 1; i++) {
                e[j] += x[i] * x_n(xx[j - 1], i - 1);
            }
            esum += (e[j] - yy[j - 1]) * (e[j] - yy[j - 1]);
        }

        System.out.println("平方误差:" + esum);


    }
}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    评论
  • 4
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值