数值方法 最小二乘法拟合多项式
程序员文章站
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);
}
}
上一篇: 【计算方法】数值积分
下一篇: 前端神器 webstorm 使用技巧