《計算方法》 李曉紅等 第三章 解線性方程組的直接法 例題 代碼

#include "stdafx.h"

#include <math.h>

// 解線性方程組的直接法

 

void PS(double A[], int n, char *name);

void GaussXiaoQu()

{

    printf("高斯直接消元法:\n");

    double a[3][3] = {{2,4,-2},{1,-1,5},{4,1,-2}};

    double b[3] = {6,0,2};

    double x[3];

 

    int n = 3;

    int k,i,j;

    double l;

 

    // 消元

    for (k = 0; k < n-1; k++)

    {

        for (i = k+1; i < n; i++)

        {

            l = a[i][k]/a[k][k];

            b[i] = b[i] - l*b[k];

            for (j = k; j < n; j++)

            {

                a[i][j] = a[i][j] - l*a[k][j];

            }

        }          

    }

    // 消元結果

    for (i = 0; i < n; i++)

    {

        for (j = 0; j < n; j++)

            printf("%f\t",a[i][j]);

        printf("%f",b[i]);

        printf("\n");

    }

    // 回代

    for (i = n-1; i >= 0; i--)

    {

        x[i] = b[i];

        for (j = n-1; j > i; j--)

            x[i] = x[i] - a[i][j]*x[j];

        x[i] = x[i] / a[i][i];

    }

    printf("x= ");

    for(i = 0; i < n; i++)

        printf("%f\t",x[i]);

    printf("\n");

}

 

void GaussLieZhuYuan()

{

    printf("高斯列主元法:\n");

    double a[3][3] = {{1,2,3},{5,4,10},{3,-0.1,1}};

    double b[3] = {1,0,2};

    double x[3];

 

    int n = 3;  // 係數矩陣維數

    int k,i,j;

    double l;

    double tmp;

    int r;

 

    // 消元

    for (k = 0; k < n-1; k++)

    {

        // 找到該列最大元

        for (r=k,j=k+1; j < n; j++) {

            if (abs(a[j][k]) > abs(a[r][k]))

            {

                r = j;

            }

        }

        // 行交換

        if (r != k)

        {

            for (j = k; j < n; j++) {

                tmp = a[k][j];

                a[k][j] = a[r][j];

                a[r][j] = tmp;

            }

            tmp = b[k];

            b[k] = b[r];

            b[r] = tmp;

        }

        // 消元

        for (i = k+1; i < n; i++)

        {

            l = a[i][k]/a[k][k];

            b[i] = b[i] - l*b[k];

            for (j = k; j < n; j++)

            {

                a[i][j] = a[i][j] - l*a[k][j];

            }

        }          

    }

    // 消元結果

    for (i = 0; i < n; i++)

    {

        for (j = 0; j < n; j++)

            printf("%f\t",a[i][j]);

        printf("%f",b[i]);

        printf("\n");

    }

    // 回代

    for (i = n-1; i >= 0; i--)

    {

        x[i] = b[i];

        for (j = n-1; j > i; j--)

            x[i] = x[i] - a[i][j]*x[j];

        x[i] = x[i] / a[i][i];

    }

    printf("x= ");

    for (i = 0; i < n; i++) {

        printf("%f\t",x[i]);

    }

    printf("\n");

}

 

void GaussQuanZhuYuan()

{

    printf("高斯全主元法:\n");

    double a[3][3] = {{1,2,3},{5,4,10},{3,-0.1,1}};

    double b[3] = {1,0,2};

    double x[3];

    double y[3];

 

    int n = 3;  // 係數矩陣維數

    int k,i,j;

    double l;

    double tmp;

    int r,c;

    int p[3] = {0,1,2},q;

    // 消元

    for (k = 0; k < n-1; k++)

    {

        // 找到子矩陣內最大元

        r = c = k;

        for (i = k; i < n; i++) {

            for (j = k; j < n; j++) {

                if (abs(a[i][j]) > abs(a[r][c]))

                {

                    r = i;

                    c = j;

                }

            }

        }

 

        // 行交換 k~r

        if (r != k)

        {

            for (j = k; j < n; j++) {

                tmp = a[k][j];

                a[k][j] = a[r][j];

                a[r][j] = tmp;

            }

            tmp = b[k];

            b[k] = b[r];

            b[r] = tmp;

        }

        // 交換列 k~c

        if (c != k)

        {

            for (i = 0; i < n; i++) {

                tmp = a[i][k];

                a[i][k] = a[i][c];

                a[i][c] = tmp;

            }

            q = p[k];

            p[k] = p[c];

            p[c] = q;

        }

        // 消元

        for (i = k+1; i < n; i++)

        {

            l = a[i][k]/a[k][k];

            b[i] = b[i] - l*b[k];

            for (j = k; j < n; j++)

            {

                a[i][j] = a[i][j] - l*a[k][j];

            }

        }          

    }

    // 消元結果

    for (i = 0; i < n; i++)

    {

        for (j = 0; j < n; j++)

            printf("%f\t",a[i][j]);

        printf("%f",b[i]);

        printf("\n");

    }

    // 回代

    for (i = n-1; i >= 0; i--)

    {

        x[i] = b[i];

        for (j = n-1; j > i; j--)

            x[i] = x[i] - a[i][j]*x[j];

        x[i] = x[i] / a[i][i];

    }

     

    printf("x= ");

    for (i = 0; i < n; i++) {

        for (j = 0; j < n; j++)

        {

            if (i == p[j])

            {

                y[i] = x[j];

            }

        }

        printf("%f\t",y[i]);

    }

    printf("\n");

}

 

void GaussYueDangMethod()

{

    printf("高斯約當消去法(列主元):\n");

    double a[3][3] = {{1,-1,0},{2,2,3},{-1,2,1}};

    double b[3] = {1,0,0};

    double x[3];

 

    int n = 3;  // 係數矩陣維數

    int k,i,j;

    double l;

    double tmp;

    int r;

 

    // 消元

    for (k = 0; k < n; k++)

    {

        // 找到該列最大元

        for (r=k,j=k+1; j < n; j++) {

            if (abs(a[j][k]) > abs(a[r][k]))

            {

                r = j;

            }

        }

        // 行交換

        if (r != k)

        {

            for (j = k; j < n; j++) {

                tmp = a[k][j];

                a[k][j] = a[r][j];

                a[r][j] = tmp;

            }

            tmp = b[k];

            b[k] = b[r];

            b[r] = tmp;

        }

        // 消元

        for (i = 0; i < n; i++) {

            if (i == k)

                continue;

            else

            {

                l = a[i][k]/a[k][k];

                b[i] = b[i] - l*b[k];

                for (j = k; j < n; j++)

                {

                    a[i][j] = a[i][j] - l*a[k][j];

                }

            }

        }

        // 消去本行

        l = a[k][k];

        for (j = k; j < n; j++)

            a[k][j] = a[k][j] / l;

        b[k] = b[k] / l;

        // 消元結果

        for (i = 0; i < n; i++)

        {

            for (j = 0; j < n; j++)

                printf("%f\t",a[i][j]);

            printf("%f",b[i]);

            printf("\n");

        }

        printf("\n");

    }

/*  // 消元結果

    for (i = 0; i < n; i++)

    {

        for (j = 0; j < n; j++)

            printf("%f\t",a[i][j]);

        printf("%f",b[i]);

        printf("\n");

    }

*/  // 回代

    for (i = n-1; i >= 0; i--)

    {

        x[i] = b[i];

    }

    printf("x= ");

    for (i = 0; i < n; i++) {

        printf("%f\t",x[i]);

    }

    printf("\n");

}

 

void ZhuiGanMethod_I()

{

    printf("三對角方程追趕法I:\n");

    double p[3];

    double q[2];

    double a[3][3] = {{6,1,0},{1,4,1},{6,1,14}};

    double d[3] = {6,24,322};

    double x[3];

    int k;

    int n = 3;

    double l;

 

    p[0] = d[0]/a[0][0];

    q[0] = a[0][1]/a[0][0];

    for (k = 1; k < n; k++) {

        l = a[k][k] - a[k][k-1]*q[k-1];

        p[k] = (d[k]-a[k][k-1]*p[k-1])/l;

        if(k<n-1)q[k] = a[k][k+1]/l;

    }

    // p,q結果

    for (k = 0; k < n; k++)

        printf("p[%d]=%f\t",k,p[k]);

    printf("\n");

    for (k = 0; k < n-1; k++)

        printf("q[%d]=%f\t",k,q[k]);

    printf("\n");

    // 回代

    x[n-1] = p[n-1];

    for (k = n-2; k >= 0; k--) {

        x[k] = p[k]-q[k]*x[k+1];

    }

    for (k = 0; k < n; k++) {

        printf("%f\t",x[k]);

    }

    printf("\n");

}

 

void ZhiJieSanJiaoXing()

{

    printf("直接三角形分解法:\n");

    double a[3][3] = {{2,2,3},{4,7,7},{-2,4,5}};

    double b[3] = {3,1,-7};

     

    double l[3][3],u[3][3];

    int n = 3;

    int i,j;

 

    // LU分解

    int k = 0;;

    int r;

 

    for (k = 0; k < n; k++) {

        // 先計算u

        for (j = 0; j < n; j++) {

            if(j<k) u[k][j]=0.;

            else

            {

                u[k][j] = a[k][j];

                for (r = 0; r < k && k > 0; r++) {

                    u[k][j] -= l[k][r]*u[r][j];

                }

            }

        }

        // 後計算l

 

        for (i = 0; i < n; i++) {

 

            if (i<k) l[i][k]=0.;

            else if(i==k) l[i][k]=1.;

            else

            {

                l[i][k] = a[i][k];

                for (r = 0; r < k && k > 0; r++) {

                    l[i][k] -= l[i][r]*u[r][k];

                }

                l[i][k] /= u[k][k];

            }

        }

    }

    printf("l=\n");

    for (i = 0; i < n; i++)

    {

        for (j = 0; j < n; j++)

            printf("%f\t",l[i][j]);

        printf("\n");

    }

    printf("u=\n");

    for (i = 0; i < n; i++)

    {

        for (j = 0; j < n; j++)

            printf("%f\t",u[i][j]);

        printf("\n");

    }

 

    // 回代 求y

    // Ly = b

    double y[3];

    y[0] = b[0];

    for (i = 1; i < n; i++) {

        y[i] = b[i];

        for (j = 0; j < i; j++) {

            y[i] = y[i] - l[i][j]*y[j];

        }

    }

    // 求x

    //Ux=y

    double x[3];

    x[n-1] = y[n-1]/u[n-1][n-1];

    for (i = n-2; i >=0; i--) {

        x[i] = y[i];

        for (j = i+1; j < n; j++) {

            x[i] = x[i] - u[i][j]*x[j];

        }

        x[i] /= u[i][i];

    }

 

    printf("x= ");

    for (i = 0; i < n; i++) {

        printf("%f\t",x[i]);

    }

    printf("\n");

}

 

 

 

 

void ZhuiGanMethod_II()

{

    printf("三對角方程追趕法II:\n");

    double p[3];

    double q[2];

    double a[3][3] = {{6,1,0},{1,4,1},{0,1,14}};

    double d[3] = {6,24,322};

    double x[3],y[3];

    int i;

    int n = 3;

     

    // 追

    p[0] = a[0][0];

    q[0] = a[0][1]/p[0];

    for (i = 1; i < n; i++)

    {

        p[i] = a[i][i] - a[i][i-1]*q[i-1];

        if (i<n-1) q[i] = a[i][i+1]/p[i];

    }

    PS(p,n,"p");PS(q,n-1,"q");

    // 趕

    for (i=0;i<n;i++)

    {

        y[i] = d[i];

        if(i>0) y[i] -= a[i][i-1]*y[i-1];

        y[i] /= p[i];

    }

    for (i=n-1;i>=0;i--) {

        x[i] = y[i];

        if(i<n-1) x[i]-=q[i]*x[i+1];

    }

    PS(y,n,"y");PS(x,n,"x");

}

 

 

void PingFangGenMethod()

{

    printf("平方根法: A=LL'\n");

    double a[3][3] = {{6,1,0},{1,4,1},{0,1,14}};

    double b[3] = {6,24,322};

    int n = 3;

    int i,j,k;

    double l[3][3];

    double x[3],y[3];

 

    for (i=0;i<n;i++) {

        for (j=0;j<n;j++) {

            l[i][j] = 0.;

        }

    }

    // 分解

    for (i=0;i<n;i++) {

        // 對角元

        l[i][i] = a[i][i];

        for (k=0;k<i;k++) {

            l[i][i] -= l[i][k]*l[i][k];

        }

        l[i][i] = sqrt(l[i][i]);

        // 列元

        for (j=i+1;j<n;j++) {

            l[j][i] = a[j][i];

            for (k=0;k<i;k++) {

                l[j][i] -= l[j][k]*l[i][k];  // 轉置!

            }

            l[j][i] /= l[i][i];

        }

    }

    printf("l=\n");

    for (i = 0; i < n; i++)

    {

        for (j = 0; j < n; j++)

            printf("%f\t",l[i][j]);

        printf("\n");

    }

    // 回代 ,L'y = b

    for (i=0;i<n;i++)

    {

        y[i] = b[i];

        for (j=0;j<i;j++) {

            y[i] -= l[i][j]*y[j];  

        }

        y[i] /= l[i][i];

    }

    for (i=n-1;i>=0;i--) {

        x[i] = y[i];

        for(j=n-1;j>i;j--)

            x[i]-=l[j][i]*x[j]; // 主意L 轉置, L' x = y

        x[i] /= l[i][i];

    }

    PS(y,n,"y");PS(x,n,"x");

}

 

void GaiJinPingFangMethod() //

{

    printf("改進的平方根法: A=LDL'\n");

     

    double a[3][3] = {{6,1,0},{1,4,1},{0,1,14}};

    double b[3] = {6,24,322};

    int n = 3;

    int i,j,k;

    double l[3][3],u[3][3];

 

    for (i=0;i<n;i++) {

        for (j=0;j<n;j++) {

            u[i][j] = l[i][j] = 0.;

        }

    }

 

    // LU分解

    int r;

 

    for (k = 0; k < n; k++) {

        // 先計算u

        for (j = k; j < n; j++) {

            u[k][j] = a[k][j];

            for (r = 0; r < k && k > 0; r++) {

                u[k][j] -= l[k][r]*u[r][j];

            }

        }

        // 後計算l, 主意與緊湊格式法差異,運算量減少

        l[k][k] = 1.;

        for (i = k+1; i < n; i++) {

            l[i][k] = u[k][i]/u[k][k];

        }

    }

    printf("l=\n");

    for (i = 0; i < n; i++)

    {

        for (j = 0; j < n; j++)

            printf("%f\t",l[i][j]);

        printf("\n");

    }

    printf("u=\n");

    for (i = 0; i < n; i++)

    {

        for (j = 0; j < n; j++)

            printf("%f\t",u[i][j]);

        printf("\n");

    }

    // 回代 求y

    // Ly = b

    double y[3];

    y[0] = b[0];

    for (i = 1; i < n; i++) {

        y[i] = b[i];

        for (j = 0; j < i; j++) {

            y[i] = y[i] - l[i][j]*y[j];

        }

    }

    // 求x

    //Ux=y

    double x[3];

    x[n-1] = y[n-1]/u[n-1][n-1];

    for (i = n-2; i >=0; i--) {

        x[i] = y[i];

        for (j = i+1; j < n; j++) {

            x[i] = x[i] - u[i][j]*x[j];

        }

        x[i] /= u[i][i];

    }

    PS(x,n,"x");

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章