最小二乘法 多项式拟合 C语言实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sunshineacm/article/details/79069561

最小二乘法 多项式拟合 C语言实现

标签:计算方法实验

拟合结果:
pic

/*
    本实验根据数组x[], y[]列出的一组数据,用最小二乘法求它的拟合曲线。
    近似解析表达式为y = a0 + a1 * x + a2 * x^2 + a3 * x^3;
*/
#include <stdio.h>
#include <math.h>

#define maxn 12
#define rank_ 3

int main(){
    double x[maxn] = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55};
    double y[maxn] = {0, 1.27, 2.16, 2.86, 3.44, 3.87, 4.15, 4.37, 4.51, 4.58, 4.02, 4.64};
    double atemp[2 * (rank_ + 1)] = {0}, b[rank_ + 1] = {0}, a[rank_ + 1][rank_ + 1];
    int i, j, k;

    for(i = 0; i < maxn; i++){  //
        atemp[1] += x[i];
        atemp[2] += pow(x[i], 2);
        atemp[3] += pow(x[i], 3);
        atemp[4] += pow(x[i], 4);
        atemp[5] += pow(x[i], 5);
        atemp[6] += pow(x[i], 6);
        b[0] += y[i];
        b[1] += x[i] * y[i];
        b[2] += pow(x[i], 2) * y[i];
        b[3] += pow(x[i], 3) * y[i];
    }

    atemp[0] = maxn;
    /*
    for(i = 0; i <= 2 * rank_; i++)  printf("atemp[%d] = %f\n", i, atemp[i]);
    printf("\n");
    for(i = 0; i <= rank_; i++)  printf("b[%d] = %f\n", i, b[i]);
    printf("\n");
    */
    for(i = 0; i < rank_ + 1; i++){  //构建线性方程组系数矩阵,b[]不变
        k = i;
        for(j = 0; j < rank_ + 1; j++)  a[i][j] = atemp[k++];
    }
    /*
    for(i = 0; i < rank_ + 1; i++){
        for(j = 0; j < rank_ + 1; j++)  printf("a[%d][%d] = %-17f  ", i, j, a[i][j]);
        printf("\n");
    }
    printf("\n");
    */

    //以下为高斯列主元消去法解线性方程组
    for(k = 0; k < rank_ + 1 - 1; k++){  //n - 1列
        int column = k;
        double mainelement = a[k][k];

        for(i = k; i < rank_ + 1; i++)  //找主元素
            if(fabs(a[i][k]) > mainelement){
                mainelement = fabs(a[i][k]);
                column = i;
            }
        for(j = k; j < rank_ + 1; j++){  //交换两行
            double atemp = a[k][j];
            a[k][j] = a[column][j];
            a[column][j] = atemp;
        }
        double btemp = b[k];
        b[k] = b[column];
        b[column] = btemp;

        for(i = k + 1; i < rank_ + 1; i++){  //消元过程
            double Mik = a[i][k] / a[k][k];
            for(j = k; j < rank_ + 1; j++)  a[i][j] -= Mik * a[k][j];
            b[i] -= Mik * b[k];
        }
    }
    /*
    for(i = 0; i < rank_ + 1; i++){  //经列主元高斯消去法得到的上三角阵(最后一列为常系数)
        for(j = 0; j < rank_ + 1; j++)  printf("%20f", a[i][j]);
        printf("%20f\n", b[i]);
    }
    printf("\n");
    */
    b[rank_ + 1 - 1] /= a[rank_ + 1 - 1][rank_ + 1 - 1];  //回代过程
    for(i = rank_ + 1 - 2; i >= 0; i--){
        double sum = 0;
        for(j = i + 1; j < rank_ + 1; j++)  sum += a[i][j] * b[j];
        b[i] = (b[i] - sum) / a[i][i];
    }
    //高斯列主元消去法结束

    printf("P(x) = %f%+fx%+fx^2%+fx^3\n\n", b[0], b[1], b[2], b[3]);
    /*
    for(i = 0; i < maxn; i++){  //误差比较
        double temp = b[0] + b[1] * x[i] + b[2] * x[i] * x[i] + b[3] * x[i] * x[i] * x[i];
        printf("%f    %f    error: %f\n", y[i], temp, temp - y[i]);
    }
    */

    return 0;
}

实验结果:
output1
去掉/* */注释后(易查错):
output2

//清新版
/*
    本实验根据数组x[], y[]列出的一组数据,用最小二乘法求它的拟合曲线。
    近似解析表达式为y = a0 + a1 * x + a2 * x^2 + a3 * x^3;
*/
#include <stdio.h>
#include <math.h>

#define maxn 12
#define rank_ 3

int main(){
    double x[maxn] = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55};
    double y[maxn] = {0, 1.27, 2.16, 2.86, 3.44, 3.87, 4.15, 4.37, 4.51, 4.58, 4.02, 4.64};
    double atemp[2 * (rank_ + 1)] = {0}, b[rank_ + 1] = {0}, a[rank_ + 1][rank_ + 1];
    int i, j, k;

    for(i = 0; i < maxn; i++){  //
        atemp[1] += x[i];
        atemp[2] += pow(x[i], 2);
        atemp[3] += pow(x[i], 3);
        atemp[4] += pow(x[i], 4);
        atemp[5] += pow(x[i], 5);
        atemp[6] += pow(x[i], 6);
        b[0] += y[i];
        b[1] += x[i] * y[i];
        b[2] += pow(x[i], 2) * y[i];
        b[3] += pow(x[i], 3) * y[i];
    }

    atemp[0] = maxn;

    for(i = 0; i < rank_ + 1; i++){  //构建线性方程组系数矩阵,b[]不变
        k = i;
        for(j = 0; j < rank_ + 1; j++)  a[i][j] = atemp[k++];
    }

    //以下为高斯列主元消去法解线性方程组
    for(k = 0; k < rank_ + 1 - 1; k++){  //n - 1列
        int column = k;
        double mainelement = a[k][k];

        for(i = k; i < rank_ + 1; i++)  //找主元素
            if(fabs(a[i][k]) > mainelement){
                mainelement = fabs(a[i][k]);
                column = i;
            }
        for(j = k; j < rank_ + 1; j++){  //交换两行
            double atemp = a[k][j];
            a[k][j] = a[column][j];
            a[column][j] = atemp;
        }
        double btemp = b[k];
        b[k] = b[column];
        b[column] = btemp;

        for(i = k + 1; i < rank_ + 1; i++){  //消元过程
            double Mik = a[i][k] / a[k][k];
            for(j = k; j < rank_ + 1; j++)  a[i][j] -= Mik * a[k][j];
            b[i] -= Mik * b[k];
        }
    }

    b[rank_ + 1 - 1] /= a[rank_ + 1 - 1][rank_ + 1 - 1];  //回代过程
    for(i = rank_ + 1 - 2; i >= 0; i--){
        double sum = 0;
        for(j = i + 1; j < rank_ + 1; j++)  sum += a[i][j] * b[j];
        b[i] = (b[i] - sum) / a[i][i];
    }
    //高斯列主元消去法结束

    printf("P(x) = %f%+fx%+fx^2%+fx^3\n\n", b[0], b[1], b[2], b[3]);

    return 0;
}

实验结果:
answer

阅读更多
换一批

没有更多推荐了,返回首页