欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-05 17:25:42
...

给定数据点(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);


    }
}

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

相关标签: 数值计算方法