C语言解线性方程组

C语言解线性方程组

情况是这样,我->对象->C语言作业->解线性方程组。

文章目录

  • C语言解线性方程组
    • 1.一般的高斯消元解法(完整代码在小节最后)
    • 2.Cholesky法求正定对称矩阵的线性方程组(完整代码在小结最后)
    • 3.追赶法解线性方程组(待更新)

1.一般的高斯消元解法(完整代码在小节最后)

高斯消元解法的思想就是,对系数矩阵A做初等行变换,得到一个上三角矩阵,从最后一行开始,逐个解方程组。
这里考虑的情况是系数矩阵A满秩,所以最后一行只有对角线上有一个非零元素,可以直接得到 x n x_n xn的解;
它的上一层有两个非零元素,其中 x n x_n xn已求得,故可以一步计算出 x n − 1 x_{n-1} xn1

依此类推,便可以求得所有的未知数 x 1 , 2 , . . . , n x_{1,2,...,n} x1,2,...,n

例子如下:
C语言解线性方程组_第1张图片
C语言解线性方程组_第2张图片
初等行变化函数:

//这里函数把A处理为上三角矩阵,但没有处理为标准上三角矩阵,即不保证每一行的首个非零元素为1
void rowTrans(double array[MAX][MAX], int n){
    // 做初等行变换
    int i,j,k;
    double tmp;             //暂存乘积因子
    double zero=1e-6;       //两浮点数差距小于1e-6视为相等

    for(i=0;i<n-1;i++){
        k=1;
        while(fabs(array[i][i]-0.0)<zero && i+k<n){
            swapArray(array,i,i+(k++),n);
        }

        for(j=i+1;j<n;j++){
			if(array[j][i]==0.0)			//如为0则那一行不用化简 
				continue;
			else{
				tmp = -(double)array[j][i]/array[i][i];		//保存乘积因子 
				for(k=i;k<n;k++)
					array[j][k] += (tmp*array[i][k]);
			}
		}
    }
}

解系数矩阵A为上三角方程组的函数:

void solveUpperEquations(double A[MAX][MAX], double x[MAX], double b[MAX], int n){
    //求解系数矩阵为上三角矩阵的线性方程组
    int i,j;
    copyArray(b,x,n);
    for(i=n-1;i>=0;i--){
        for(j=i+1;j<n;j++){
            x[i]-=A[i][j]*x[j];
        }
        x[i]/=A[i][i];
    }
}

再补充一个解系数矩阵A为下三角方程组的函数:

void solveLowerEquations(double A[MAX][MAX], double x[MAX], double b[MAX], int n){
    //求解系数矩阵为下三角矩阵的线性方程组
    int i,j;
    copyArray(b,x,n);
    for(i=0;i<n;i++){
        for(j=0;j<i;j++){
            x[i]-=A[i][j]*x[j];
        }
        x[i]/=A[i][i];
    }
}

一些工具函数:

//输出矩阵内容
void printMatrix(double array[MAX][MAX], int n){
    int i,j;
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            printf("%lf",array[i][j]);
            if(j==n-1){
                printf("\n");
            }else{
                printf("\t");
            }
        }
    }
}

//输出数组内容
void printArray(double x[MAX], int n){
    int i;
    for(i=0;i<n;i++){
        printf("%lf",x[i]);
        if(i==n-1){
            printf("\n");
        }else{
            printf("\t");
        }
    }
}

//交换函数
void swap(double* a,double*b){
	double tmp = *a;
	*a = *b;
	*b = tmp;
}

//交换数组元素
void swapArray(double array[MAX][MAX],int a,int b,int n){
	int i;
	for(i=0;i<n;i++)
		swap(&array[a][i],&array[b][i]);	
}

void copyMatrix(double a[MAX][MAX], double b[MAX][MAX], int n){
    int i,j;
    for(i=0;i<n;i++){
        for(j=0;j<n;i++){
            b[i][j]=a[i][j];
        }
    }
}

void copyArray(double a[MAX], double b[MAX], int n){
    int i;
    for(i=0;i<n;i++){
        b[i]=a[i];
    }
}

完整代码如下:

#include 
#include 
#define MAX 20

void swap(double* a,double*b){
	double tmp = *a;
	*a = *b;
	*b = tmp;
}

void swapArray(double a[MAX], double b[MAX], int n){
	int i;
	for(i=0;i<n;i++)
		swap(&a[i],&b[i]);	
}

double computeDet(double array[MAX][MAX], int n){
    // 通过初等行变换,再计算对角元素乘积,来计算行列式的值

    int i,j,k;
    int sign=0;             //行列式交换一次需要改变符号,此变量记录交换次数 
    double sum=1.0;         //结果
    double tmp;             //暂存乘积因子
    double zero=1e-6;       //两浮点数差距小于1e-6视为相等

    for(i=0;i<n-1;i++){
        k=1;
        while(fabs(array[i][i]-0.0)<zero && i+k<n){
            swapArray(array[i],array[i+(k++)],n);
			sign++;
        }

        for(j=i+1;j<n;j++){
			if(array[j][i]==0.0)			//如为0则那一行不用化简 
				continue;
			else{
				tmp = -(double)array[j][i]/array[i][i];		//保存乘积因子 
				for(k=i;k<n;k++)
					array[j][k] += (tmp*array[i][k]);
			}
		}
    }

    for(i=0;i<n;i++)
		sum *= array[i][i];
	if(sign%2!=0)				//交换偶数次符仍为正 
		sum *= -1;
    return sum;
}

void rowTrans(double array[MAX][MAX], int n){
    // 做初等行变换
    int i,j,k;
    double tmp;             //暂存乘积因子
    double zero=1e-6;       //两浮点数差距小于1e-6视为相等

    for(i=0;i<n-1;i++){
        k=1;
        while(fabs(array[i][i]-0.0)<zero && i+k<n){
            swapArray(array[i],array[i+(k++)],n);
        }

        for(j=i+1;j<n;j++){
			if(array[j][i]==0.0)			//如为0则那一行不用化简 
				continue;
			else{
				tmp = -(double)array[j][i]/array[i][i];		//保存乘积因子 
				for(k=i;k<n;k++)
					array[j][k] += (tmp*array[i][k]);
			}
		}
    }

}

void rowTrans_Ab(double array[MAX][MAX], int n){
    // 做A、b同时做初等行变换
    int i,j,k;
    double tmp;             //暂存乘积因子
    double zero=1e-6;       //两浮点数差距小于1e-6视为相等

    for(i=0;i<n;i++){
        k=1;
        while(fabs(array[i][i]-0.0)<zero && i+k<n){
            swapArray(array[i],array[i+(k++)],n);
        }

        for(j=i+1;j<n;j++){
			if(array[j][i]==0.0)			//如为0则那一行不用化简 
				continue;
			else{
				tmp = -(double)array[j][i]/array[i][i];		//保存乘积因子 
				for(k=i;k<=n;k++)
					array[j][k] += (tmp*array[i][k]);
			}
		}
    }

}

void printMatrix(double array[MAX][MAX], int n){
    int i,j;
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            printf("%lf",array[i][j]);
            if(j==n-1){
                printf("\n");
            }else{
                printf("\t");
            }
        }
    }
}

void printArray(double x[MAX], int n){
    int i;
    for(i=0;i<n;i++){
        printf("%lf",x[i]);
        if(i==n-1){
            printf("\n");
        }else{
            printf("\t");
        }
    }
}

void copyMatrix(double a[MAX][MAX], double b[MAX][MAX], int n){
    int i,j;
    for(i=0;i<n;i++){
        for(j=0;j<n;i++){
            b[i][j]=a[i][j];
        }
    }
}

void copyArray(double a[MAX], double b[MAX], int n){
    int i;
    for(i=0;i<n;i++){
        b[i]=a[i];
    }
}

void solveLowerEquations(double A[MAX][MAX], double x[MAX], double b[MAX], int n){
    //求解系数矩阵为下三角矩阵的线性方程组
    int i,j;
    copyArray(b,x,n);
    for(i=0;i<n;i++){
        for(j=0;j<i;j++){
            x[i]-=A[i][j]*x[j];
        }
        x[i]/=A[i][i];
    }
}

void solveUpperEquations(double A[MAX][MAX], double x[MAX], double b[MAX], int n){
    //求解系数矩阵为上三角矩阵的线性方程组
    int i,j;
    copyArray(b,x,n);
    for(i=n-1;i>=0;i--){
        for(j=i+1;j<n;j++){
            x[i]-=A[i][j]*x[j];
        }
        x[i]/=A[i][i];
    }
}

//解一般方程
int main(){
    int i,j;
    int n;				//阶数 
    double tmp;         //临时变量
    double x[MAX];      //未知数矩阵
    double b[MAX];      //常系数矩阵
    double A[MAX][MAX]; //系数矩阵


    //数据初始化
    printf("Please enter the dimensions of the coefficient matrix:(n)");
	scanf("%d",&n);

    printf("Please enter the value of coefficient matrix:(A)\n");
	for(i=0;i<n;i++){
		for(j=0;j<n;j++)
			scanf("%lf",&A[i][j]);
	}

    printf("Please enter the value of the constant term matrix:(b)\n");
    for(i=0;i<n;i++){
        scanf("%lf",&b[i]);
    }

	//初始化x和Ab
    for(i=0;i<n;i++){
        x[i]=0.0;
        A[i][n]=b[i];
    }

    //对矩阵A做初等行变换
    rowTrans_Ab(A,n);
    
    printf("rowTrans:\n");
	printMatrix(A,n);
    
    //取变化后的b
    for(i=0;i<n;i++){
        b[i]=A[i][n];
    }

    //解上三角矩阵
    solveUpperEquations(A,x,b,n);

    //输出结果
    printf("The result are:\n");
    printArray(x,n);
    return 0;
}

2.Cholesky法求正定对称矩阵的线性方程组(完整代码在小结最后)

Cholesky分解又称平方分解法,是把一个正定对称的矩阵表示成一个下三角矩阵L和其转置的乘积的分解。
已知,满秩矩阵可以做LU分解,同理也可以LDU分解。
对于一个正定对称矩阵,它显然也可以做LDU分解,不过特殊的是,把D对角线上的每个元素都开平方,分别乘给L和U,则可以得到 L L L L T L^T LT,使得 A = L ∗ L T A=L*L^T A=LLT
我使用的求法是,给系数矩阵A做(没有整除某个非零数的,即不刻意得把每一行的非零首元化为1)初等行变换,得到上三角矩阵。该方法得到的上三角矩阵即为DU,对D对角线上的每个元素做平方处理,得到的结果再与U相乘,即得到 L T L^T LT

例子如下:
C语言解线性方程组_第3张图片

C语言解线性方程组_第4张图片

C语言解线性方程组_第5张图片
完整代码如下:

#include 
#include 
#define MAX 20

void swap(double* a,double*b){
	double tmp = *a;
	*a = *b;
	*b = tmp;
}

void swapArray(double a[MAX], double b[MAX], int n){
	int i;
	for(i=0;i<n;i++)
		swap(&a[i],&b[i]);	
}

double computeDet(double array[MAX][MAX], int n){
    // 通过初等行变换,再计算对角元素乘积,来计算行列式的值

    int i,j,k;
    int sign=0;             //行列式交换一次需要改变符号,此变量记录交换次数 
    double sum=1.0;         //结果
    double tmp;             //暂存乘积因子
    double zero=1e-6;       //两浮点数差距小于1e-6视为相等

    for(i=0;i<n-1;i++){
        k=1;
        while(fabs(array[i][i]-0.0)<zero && i+k<n){
            swapArray(array[i],array[i+(k++)],n);
			sign++;
        }

        for(j=i+1;j<n;j++){
			if(array[j][i]==0.0)			//如为0则那一行不用化简 
				continue;
			else{
				tmp = -(double)array[j][i]/array[i][i];		//保存乘积因子 
				for(k=i;k<n;k++)
					array[j][k] += (tmp*array[i][k]);
			}
		}
    }

    for(i=0;i<n;i++)
		sum *= array[i][i];
	if(sign%2!=0)				//交换偶数次符仍为正 
		sum *= -1;
    return sum;

}

void rowTrans(double array[MAX][MAX], int n){
    // 做初等行变换
    int i,j,k;
    double tmp;             //暂存乘积因子
    double zero=1e-6;       //两浮点数差距小于1e-6视为相等

    for(i=0;i<n-1;i++){
        k=1;
        while(fabs(array[i][i]-0.0)<zero && i+k<n){
            swapArray(array[i],array[i+(k++)],n);
        }

        for(j=i+1;j<n;j++){
			if(array[j][i]==0.0)			//如为0则那一行不用化简 
				continue;
			else{
				tmp = -(double)array[j][i]/array[i][i];		//保存乘积因子 
				for(k=i;k<n;k++)
					array[j][k] += (tmp*array[i][k]);
			}
		}
    }

}

void rowTrans_Ab(double array[MAX][MAX], int n){
    // 做A、b同时做初等行变换
    int i,j,k;
    double tmp;             //暂存乘积因子
    double zero=1e-6;       //两浮点数差距小于1e-6视为相等

    for(i=0;i<n;i++){
        k=1;
        while(fabs(array[i][i]-0.0)<zero && i+k<n){
            swapArray(array[i],array[i+(k++)],n);
        }

        for(j=i+1;j<n;j++){
			if(array[j][i]==0.0)			//如为0则那一行不用化简 
				continue;
			else{
				tmp = -(double)array[j][i]/array[i][i];		//保存乘积因子 
				for(k=i;k<=n;k++)
					array[j][k] += (tmp*array[i][k]);
			}
		}
    }

}

void printMatrix(double array[MAX][MAX], int n){
    int i,j;
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            printf("%lf",array[i][j]);
            if(j==n-1){
                printf("\n");
            }else{
                printf("\t");
            }
        }
    }
}

void printArray(double x[MAX], int n){
    int i;
    for(i=0;i<n;i++){
        printf("%lf",x[i]);
        if(i==n-1){
            printf("\n");
        }else{
            printf("\t");
        }
    }
}

void copyMatrix(double a[MAX][MAX], double b[MAX][MAX], int n){
    int i,j;
    for(i=0;i<n;i++){
        for(j=0;j<n;i++){
            b[i][j]=a[i][j];
        }
    }
}

void copyArray(double a[MAX], double b[MAX], int n){
    int i;
    for(i=0;i<n;i++){
        b[i]=a[i];
    }
}

void transpose(double a[MAX][MAX], int n){
    int i,j;
    for(i=0;i<n-1;i++){
        for(j=i+1;j<n;j++){
            swap(&a[i][j], &a[j][i]);
        }
    }
}

void solveLowerEquations(double A[MAX][MAX], double x[MAX], double b[MAX], int n){
    //求解系数矩阵为下三角矩阵的线性方程组
    int i,j;
    copyArray(b,x,n);
    for(i=0;i<n;i++){
        for(j=0;j<i;j++){
            x[i]-=A[i][j]*x[j];
        }
        x[i]/=A[i][i];
    }
}

void solveUpperEquations(double A[MAX][MAX], double x[MAX], double b[MAX], int n){
    //求解系数矩阵为上三角矩阵的线性方程组
    int i,j;
    copyArray(b,x,n);
    for(i=n-1;i>=0;i--){
        for(j=i+1;j<n;j++){
            x[i]-=A[i][j]*x[j];
        }
        x[i]/=A[i][i];
    }
}


int main(){
    int i,j;
    int n;				//阶数 
    double tmp;         //临时变量
    double x[MAX];      //未知数矩阵
    double A[MAX][MAX];  //系数矩阵
    double b[MAX];       //常系数矩阵
	
    //数据初始化
    printf("Please enter the dimensions of the coefficient matrix:(n)");
	scanf("%d",&n);

    printf("Please enter the value of coefficient matrix:(A)\n");
	for(i=0;i<n;i++){
		for(j=0;j<n;j++)
			scanf("%lf",&A[i][j]);
	}

    printf("Please enter the value of the constant term matrix:(b)\n");
    for(i=0;i<n;i++){
        scanf("%lf",&b[i]);
    }

    for(i=0;i<n;i++){
        x[i]=0.0;
    }

    //对矩阵A做初等行变换
    rowTrans(A,n);
    printf("rowTrans:\n");
	printMatrix(A,n);

    //处理主元,得到L.T(上三角矩阵)
    for(i=0;i<n;i++){
        if(A[i][i]<0){
            for(j=i;j<n;j++){
                A[i][j]*=-1;
            }
        }
        if(A[i][i]!=1){
            tmp=sqrt(A[i][i]);
            for(j=i;j<n;j++){
                A[i][j]/=tmp;
            }
        }
        
    }
    printf("L.T:\n");
    printMatrix(A,n);

    //求得L(下三角矩阵),求解第一步方程Ly=b,求得y
    transpose(A,n);
    printf("L:\n");
    printMatrix(A,n);

    solveLowerEquations(A,x,b,n);
    printf("y:\n");
    printArray(x,n);

    //求得L.T(上三角矩阵),求解第二步方程L.T*x=y,求得x
    transpose(A,n);
    copyArray(x,b,n);//x中暂存的y赋给b
    solveUpperEquations(A,x,b,n);

    printf("The result are:\n");
    printArray(x,n);
    return 0;
    //期望结果:(1,-1,0,2,1,-1,0,2)
}

3.追赶法解线性方程组(待更新)

你可能感兴趣的:(c语言,算法,开发语言)