A. 高斯先列主消元法求解线性方程组AX=b C语言
其中用到了高斯先列主消元法 #include <iostream.h>
#include <stdlib.h>
#include <math.h>
/*楼竞网站www.LouJing.com
拥有该程序的版权,转载请保留该版权.
谢谢合作!*/
double* allocMem(int ); //分配内存空间函数
void GaussLineMain(double*,double*,double*,int );//采用高斯列主元素消去法求解x的初始向量值
void Jacobi(double*,double*,double*,double*,int,int);//利用雅可比迭代公式求解x的值
void main()
{
short matrixNum; //矩阵的行数(列数)
double *matrixA; //矩阵A,初始系数矩阵
double *matrixD; //矩阵D为A中的主对角阵
double *matrixL; //矩阵L为A中的下三角阵
double *matrixU; //矩阵U为A中的上三角阵
double *B; //矩阵B为雅可比方法迭代矩阵
double *f; //矩阵f为中间的过渡的矩阵
double *x; //x为一维数组,存放结果
double *xk; //xk为一维数组,用来在迭代中使用
double *b; //b为一维数组,存放方程组右边系数
int i,j,k;
cout<<"<<请输入矩阵的行数(列数与行数一致)>>:";
cin>>matrixNum;
//分别为A、D、L、U、B、f、x、b分配内存空间
matrixA=allocMem(matrixNum*matrixNum);
matrixD=allocMem(matrixNum*matrixNum);
matrixL=allocMem(matrixNum*matrixNum);
matrixU=allocMem(matrixNum*matrixNum);
B=allocMem(matrixNum*matrixNum);
f=allocMem(matrixNum);
x=allocMem(matrixNum);
xk=allocMem(matrixNum);
b=allocMem(matrixNum);
//输入系数矩阵各元素值
cout<<endl<<endl<<endl<<"<<请输入矩阵中各元素值(为 "<<matrixNum<<"*"<<matrixNum<<",共计 "<<matrixNum*matrixNum<<" 个元素)"<<">>:"<<endl<<endl;
for(i=0;i<matrixNum;i++)
{
cout<<"请输入矩阵中第 "<<i+1<<" 行的 "<<matrixNum<<" 个元素:";
for(j=0;j<matrixNum;j++)
cin>>*(matrixA+i*matrixNum+j);
}
//输入方程组右边系数b的各元素值
cout<<endl<<endl<<endl<<"<<请输入方程组右边系数各元素值,共计 "<<matrixNum<<" 个"<<">>:"<<endl<<endl;
for(i=0;i<matrixNum;i++)
cin>>*(b+i);
/* 下面将A分裂为A=D-L-U */
//首先将D、L、U做初始化工作
for(i=0;i<matrixNum;i++)
for(j=0;j<matrixNum;j++)
*(matrixD+i*matrixNum+j)=*(matrixL+i*matrixNum+j)=*(matrixU+i*matrixNum+j)=0;
//D、L、U分别得到A的主对角线、下三角和上三角;其中D取逆矩阵、L和U各元素取相反数
for(i=0;i<matrixNum;i++)
for(j=0;j<matrixNum;j++)
if(i==j&&*(matrixA+i*matrixNum+j)) *(matrixD+i*matrixNum+j)=1/(*(matrixA+i*matrixNum+j));
else if(i>j) *(matrixL+i*matrixNum+j)=-*(matrixA+i*matrixNum+j);
else *(matrixU+i*matrixNum+j)=-*(matrixA+i*matrixNum+j);
//求B矩阵中的元素
for(i=0;i<matrixNum;i++)
for(j=0;j<matrixNum;j++)
{
double temp=0;
for(k=0;k<matrixNum;k++)
temp+=*(matrixD+i*matrixNum+k)*(*(matrixL+k*matrixNum+j)+*(matrixU+k*matrixNum+j));
*(B+i*matrixNum+j)=temp;
}
//求f中的元素
for(i=0;i<matrixNum;i++)
{
double temp=0;
for(j=0;j<matrixNum;j++)
temp+=*(matrixD+i*matrixNum+j)*(*(b+j));
*(f+i)=temp;
}
/* 计算x的初始向量值 */
GaussLineMain(matrixA,x,b,matrixNum);
/* 利用雅可比迭代公式求解xk的值 */
int JacobiTime;
cout<<endl<<endl<<endl<<"<<雅可比迭代开始,请输入希望迭代的次数>>:";
cin>>JacobiTime;
while(JacobiTime<=0)
{
cout<<"迭代次数必须大于0,请重新输入:";
cin>>JacobiTime;
}
Jacobi(x,xk,B,f,matrixNum,JacobiTime);
//输出线性方程组的解 */
cout<<endl<<endl<<endl<<"<<方程组运算结果如下>>"<<endl;
cout.precision(20); //设置输出精度,以此比较不同迭代次数的结果
for(i=0;i<matrixNum;i++)
cout<<"x"<<i+1<<" = "<<*(xk+i)<<endl;
cout<<endl<<endl<<"求解过程结束..."<<endl<<endl;
//释放掉所有动态分配的内存
delete [] matrixA;
delete [] matrixD;
delete [] matrixL;
delete [] matrixU;
delete [] B;
delete [] f;
delete [] x;
delete [] xk;
delete [] b;
}
/*--------------------
分配内存空间函数
www.LouJing.com
--------------------*/
double* allocMem(int num)
{
double *head;
if((head=new double[num])==NULL)
{
cout<<"内存空间分配失败,程序终止运行!"<<endl;
exit(0);
}
return head;
}
/*---------------------------------------------
计算Ax=b中x的初始向量值,采用高斯列主元素消去法
www.LouJing.com
---------------------------------------------*/
void GaussLineMain(double* A,double* x,double* b,int num)
{
int i,j,k;
//共处理num-1行
for(i=0;i<num-1;i++)
{
//首先每列选主元,即最大的一个
double lineMax=fabs(*(A+i*num+i));
int lineI=i;
for(j=i;j<num;j++)
if(fabs(*(A+j*num+i))>fabs(lineMax)) lineI=j;
//主元所在行和当前处理行做行交换,右系数b也随之交换
for(j=i;j<num;j++)
{
//A做交换
lineMax=*(A+i*num+j);
*(A+i*num+j)=*(A+lineI*num+j);
*(A+lineI*num+j)=lineMax;
//b中对应元素做交换
lineMax=*(b+i);
*(b+i)=*(b+lineI);
*(b+lineI)=lineMax;
}
if(*(A+i*num+i)==0) continue; //如果当前主元为0,本次循环结束
//将A变为上三角矩阵,同样b也随之变换
for(j=i+1;j<num;j++)
{
double temp=-*(A+j*num+i)/(*(A+i*num+i));
for(k=i;k<num;k++)
{
*(A+j*num+k)+=temp*(*(A+i*num+k));
}
*(b+j)+=temp*(*(b+i));
}
}
/* 验证Ax=b是否有唯一解,就是验证A的行列式是否为0;
如果|A|!=0,说明有唯一解*/
double determinantA=1;
for(i=0;i<num;i++)
determinantA*=*(A+i*num+i);
if(determinantA==0)
{
cout<<endl<<endl<<"通过计算,矩阵A的行列式为|A|=0,即A没有唯一解。\n程序退出..."<<endl<<endl;
exit(0);
}
/* 从最后一行开始,回代求解x的初始向量值 */
for(i=num-1;i>=0;i--)
{
for(j=num-1;j>i;j--)
*(b+i)-=*(A+i*num+j)*(*(x+j));
*(x+i)=*(b+i)/(*(A+i*num+i));
}
}
/*------------------------------------
利用雅可比迭代公式求解x的精确值
www.LouJing.com
迭代公式为:xk=Bx+f
------------------------------------*/
void Jacobi(double* x,double* xk,double* B,double* f,int num,int time)
{
int t=1,i,j;
while(t<=time)
{
for(i=0;i<num;i++)
{
double temp=0;
for(j=0;j<num;j++)
temp+=*(B+i*num+j)*(*(x+j));
*(xk+i)=temp+*(f+i);
}
//将xk赋值给x,准备下一次迭代
for(i=0;i<num;i++)
*(x+i)=*(xk+i);
t++;
}
}
B. 用C语言写一个高斯消元法解方程组的程序
我们以方程组 2x1 + 6x2 - x3 = -12
5x1 - x2 +2x3 = 29
-3x1 - 4x2 + x3 = 5
为例 来说明楼主自己把方程组化为矩阵形式。以下为源代码 。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
int GS(int,double**,double *,double);
double **TwoArrayAlloc(int,int);
void TwoArrayFree(double **);
int main(void)
{
int i,n;
double ep,**a,*b;
n = 3;
ep = 1e-4;
a = TwoArrayAlloc(n,n);
b = (double *)calloc(n,sizeof(double));
if(b == NULL)
{
printf("memory get error\n");
exit(1);
}
a[0][0]= 2; a[0][1]= 6; a[0][2]= -1;
a[1][0]= 5; a[1][1]=-1; a[1][2]= 2;
a[2][0]=-3; a[2][1]=-4; a[2][2]= 1;
b[0] = -12; b[1] = 29; b[2] = 5;
if(!GS(n,a,b,ep))
{
printf("can't solve it with GS elimination\n");
exit(0);
}
printf("The solution of equations is as follows:\n");
for(i=0;i<3;i++)
{
printf("x%d = %.2f\n",i,b[i]);
}
TwoArrayFree(a);
free(b);
return 0;
}
int GS(n,a,b,ep)
int n;
double **a;
double *b;
double ep;
{
int i,j,k,l;
double t;
for(k=1;k<=n;k++)
{
for(l=k;l<=n;l++)
if(fabs(a[l-1][k-1])>ep)
break;
else if(l==n)
return(0);
if(l!=k)
{
for(j=k;j<=n;j++)
{
t = a[k-1][j-1];
a[k-1][j-1] =a[l-1][j-1];
a[l-1][j-1] =t;
}
t=b[k-1];
b[k-1]=b[l-1];
b[l-1]=t;
}
t=1/a[k-1][k-1];
for(j=k+1;j<=n;j++)
a[k-1][j-1]=t*a[k-1][j-1];
b[k-1]*=t;
for(i=k+1;i<=n;i++)
{
for(j=k+1;j<=n;j++)
a[i-1][j-1]-=a[i-1][k-1]*a[k-1][j-1];
b[i-1]-=a[i-1][k-1]*b[k-1];
}
}
for(i=n-1;i>=1;i--)
for(j=i+1;j<=n;j++)
b[i-1]-=a[i-1][j-1]*b[j-1];
return(1);
}
double **TwoArrayAlloc(int r,int c)
{
double *x,**y;
int n;
x=(double *)calloc(r*c,sizeof(double));
y=(double **)calloc(r,sizeof(double*));
for(n=0;n<=r-1;++n)
{
y[n]=&x[c*n];
}
return y ;
}
void TwoArrayFree(double **x)
{
free(x[0]);
free(x);
}
C. 求C语言课程设计:用高斯列主元消元法解线性方程组
这里向你推荐一下克鲁特算法(其实就是对高斯列主元消元法进行优化,使之更适合于计算机编程),首先将矩阵A进行LU分解(将系数矩阵分解成一个上三角矩阵和一个下三角矩阵),分解的过程中用到了隐式的主元寻找法,同时利用克鲁特算法可以将两个n*n矩阵压缩到一个n*n矩阵中,大大节省了存储空间提高了计算速度。
方程可化为L*U*x=B,令U*x=y --->L*y=B
然后利用回代先求y,再利用y求x
因为该方法在求解过程中不涉及增广矩阵所以矩阵B几乎不参与什么运算,所以它的计算速度应该能够达到高斯列主元消元法的三倍,但原理与其基本一致。
而且我在程序中使用了动态数组方便你今后进行扩展。
以下程序按照《矩阵论第二版》和《C语言数值计算法方法大全》编写,LU分解部分程序主要参考了《C语言数值计算法方法大全》第二章的程序
如果你需要详细的理论讲解我可以将这两本书和源程序发给你,上面的论述相当详细足够你答辩用的了,我的邮箱[email protected]
计算结果:
A矩阵:
2 2 5
3 4 7
1 3 3
B矩阵:
5
6
5
解矩阵:
x 1=-7
x 2=0.333333
x 3=3.66667
Press any key to continue
#include <cmath>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <functional>
#include <vector>
#include <algorithm>
using namespace std;
#define TINY 1.0e-20 //A small number.
#define N 3
void ludcmp(vector<vector<float> > &a, int n, vector<int> &indx, float &d);//对矩阵进行LU分解
void lubksb(vector<vector<float> > &a, int n, vector<int> &indx, vector<float> &b);//对矩阵进行前向和后向回代
void root(vector<vector<float> > &x,vector<float> &col);//解方程结果保存在y中
void iniv(vector<vector<float> > &x,vector<float> line,int n);//对二维动态数组进行初始化
void main()
{
int i,j,n=N;//输入矩阵的维数
float A[N][N]={{2,2,5},{3,4,7},{1,3,3}};//左边A矩阵
float B[N]={5,6,5};//右边B矩阵
vector<vector<float> > x;//建立动态二维数组存放A,保证你的程序进行扩展时只改A,B,N
vector<float> line;
vector<float> y(n);//建立动态数组存放B
iniv(x,line,n);
y.clear();
for(i=0;i<n;i++)//将A赋给x,B赋给y
{
y.push_back(B[i]);
for(j=0;j<n;j++)
{
x[i].push_back(A[i][j]);
}
}
cout<<"A矩阵:"<<endl;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
cout<<setw(2)<<setiosflags(ios::left)<<setw(2)<<x[i][j]<<" ";
}
cout<<endl;
}
cout<<"B矩阵:"<<endl;
for(i=0;i<n;i++)
{
cout<<setw(2)<<setiosflags(ios::left)<<setw(2)<<y[i]<<endl;
}
root(x,y);//求根
cout<<"解矩阵:"<<endl;
for(i=0;i<n;i++)
{
cout<<setw(2)<<setiosflags(ios::left)<<"x"<<i+1<<"="<<y[i]<<endl;
}
cout<<endl;
}
void root(vector<vector<float> > &x,vector<float> &col)
{
int n=x.size(),i=0,j=0;
vector<int> index(n);//用于记录寻找主元素过程中对矩阵的初等变换
index.clear();
float m=1.0;//记录变换方式,此程序中无用
ludcmp(x,n,index,m);//进行LU分解
lubksb(x,n,index,col);//根据分解结果进行回带
}
//以下程序按照《矩阵论第二版》和《C语言数值计算法方法大全》编写,LU分解部分程序主要参考了《C语言数值计算法方法大全》第二章的程序
//如果你需要详细的理论讲解我可以将这两本书和源程序发给你,我的邮箱[email protected]
void ludcmp(vector<vector<float> > &a, int n, vector<int> &indx, float &d)
{
int i,imax,j,k;
float big=0,m=0,sum=0,temp=0;
vector<float> vv(n);
vv.clear();
d=1.0;
for (i=0;i<n;i++)
{
big=0.0;
for (j=0;j<n;j++)
if ((temp=fabs(a[i][j])) > big)
big=temp;
vv[i]=1.0/big;
}
for (j=0;j<n;j++)
{
for (i=0;i<j;i++)
{
sum=a[i][j];
for (k=0;k<i;k++)
sum -= a[i][k]*a[k][j];
a[i][j]=sum;
}
big=0.0;
for (i=j;i<n;i++)
{
sum=a[i][j];
for (k=0;k<j;k++)
sum -= a[i][k]*a[k][j];
a[i][j]=sum;
if ( (m=vv[i]*fabs(sum)) >= big)
{
big=m;
imax=i;
}
}
if (j != imax)
{
for (k=0;k<n;k++)
{
m=a[imax][k];
a[imax][k]=a[j][k];
a[j][k]=m;
}
d = -(d);
vv[imax]=vv[j];
}
indx[j]=imax;
if (a[j][j] == 0.0)
a[j][j]=TINY;
if (j != n)
{
m=1.0/(a[j][j]);
for (i=j+1;i<n;i++)
a[i][j] *= m;
}
}
}
void lubksb(vector<vector<float> > &a, int n, vector<int> &indx, vector<float> &b)
{
int i,ii=0,ip,j;
float sum;
for(i=0;i<n;i++)//按LU分解时寻找主元所进行的初等变换进行反边变换。
{
ip=indx[i];
sum=b[ip];
b[ip]=b[i];
b[i]=sum;
}
sum=0;
for (i=1;i<n;i++)
{
sum=0;
for(j=0;j<i;j++)
{
sum+=a[i][j]*b[j];
}
b[i]=b[i]-sum;
}
b[n-1]=b[n-1]/a[n-1][n-1];
for (i=n-2;i>=0;i--)
{
sum=0;
for(j=i+1;j<n;j++)
{
sum+=a[i][j]*b[j];
}
b[i]=(b[i]-sum)/a[i][i];
}
}
void iniv(vector<vector<float> > &x,vector<float> line,int n)
{
int i,j;
for(i=0;i<n;i++)
{
x.push_back(line);
for(j=0;j<n;j++)
{
x[i].clear();
}
}
}
D. 用高斯消元法解三元一次方程组,C语言
参阅我的文章:http://wenku..com/view/d4ea2273650e52ea5418981d.html
#include "stdafx.h" //VS 预编译头文件,其他系统请删除
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<math.h>
#include<time.h>
//VS 2013 否决了 scanf 等函数,为了使用,加上下句。
//其他系统请删除
#pragma warning(disable:4996)
int GaussJordanElimination(int n, const double *pCoef, double *pOut);
//VS 主函数签名格式。其他系统请改变签名,如:
//int main()
int _tmain(int argc, _TCHAR* argv[])
{
double cf[3][4] = { {-0.02, 2.0, 2.0, 0.4}, {1.0, 0.78125, 0.0, 1.3816}, {3.996, 5.526, 4.0, 7.4178} };
double rs[3];
int i;
i = GaussJordanElimination(3, (double*)cf, rs);
printf("x1 = %lf, x2 = %lf, x3 = %lf\n", rs[0], rs[1], rs[2]);
system("pause"); //避免窗口一闪而退
return 0;
}
//绝对值函数
__inline double _abs(double v)
{
return v < 0 ? -v : v;
}
//线性方程组列主元高斯消元法
//n 方程元数;pCoef 系数,必须以行主序方式存放的二维数组;
//pOut 长度为 n 的一维数组(调用者负责维护),用于输出数据
//返回值:0 成功,-1 无解,1 申请内存失败, 2 不定解。
int GaussJordanElimination(int n, const double *pCoef, double *pOut)
{
double *pcf;
int rows = n, columns = n + 1;
//pcf = new double[rows * columns];
pcf = (double*)malloc(rows * columns * sizeof(double));
if (pcf == 0) return 1; //巧妇难为无米之炊,内存都申请不到,还能干嘛!
memcpy(pcf, pCoef, (rows * columns) * sizeof(double)); //据说这个运行效率很高
int r, c, i; //循环变量
int a, b;
double x, y;
//开始消元,将 pcf 方阵区处理成到直角三角形(直角在右上角)矩阵
for (r = 0; r < rows - 1; r++)
{
//选取主元
a = r; x = _abs(pcf[r * columns + r]);
for (i = r + 1; i < rows; i++)
{ //查找主元在哪行
if (x < _abs(pcf[i * columns + r])) a = i;
}
if (a > r)
{ //主元不是当前行(r),比较麻烦,需要将第 a 行与第 r 行兑换
//第 r 列前面的就不要对换了,因为这些项已经被消元,变成 0 了
for (c = r; c < columns; c++)
{
x = pcf[r * columns + c];
pcf[r * columns + c] = pcf[a * columns + c];
pcf[a * columns + c] = x;
}
}
//开始消元
a = r * columns; //记住将主元的行地址偏移量,以提高程序运行效率
x = -pcf[a + r]; //要多次使用,记下她,以提高程序运行效率
if (x == 0) //主元居然为 0,纯粹是想坑爹,岂能上当!
continue; //继续后面的消元,以便最终判断是无解还是任意解
for (i = r + 1; i < rows; i++)
{ //正在消元
b = i * columns;//记住将要消元的行地址偏移量,以提高程序运行效率
y = pcf[b + r]; //要多次使用,记下她,以提高程序运行效率
if (y != 0)
{ //y == 0,本行不需要消元
y /= x; //要多次使用,记下她,以提高程序运行效率
pcf[b + r] = 0; //肯定为 0,不用计算。
for (c = r + 1; c < columns; c++)
pcf[b + c] += pcf[a + c] * y;
}
}
}//至此,pcf 方阵区已经处理成到直角三角形(直角在右上角)矩阵
//回代,将 pcf 方阵区处理成主对角线为 1,其他为 0 的矩阵
int columns_1 = c = columns - 1; //多次用到,提高效率
for (r = rows - 1; r >= 1; r--)
{
b = r * columns;
if (pcf[b + r] == 0)
{ //经过前面的消元,除主元外,其他元应该都为 0
if (pcf[b + columns_1] == 0)
{ //常数项为 0,方程有不定解
free(pcf);
return 2;
}
else
{ //常数项为 0,方程有无解
free(pcf); //释放内存
return -1;
}
}
pcf[b + columns_1] /= pcf[b + r];
pcf[b + r] = 1; //肯定为 1,不用计算。
y = -pcf[b + columns_1];
//回代
for (i = r - 1; i >= 0; i--)
{
pcf[i * columns + columns_1] += pcf[i * columns + r] * y;
pcf[i * columns + r] = 0; //已经回代,此项已消,置为 0。
}
}
//处理第一行数据
pcf[columns_1] /= pcf[0];
pcf[0] = 1;
//至此,回代过程结束,pcf 矩阵的最后一列就是结果
//返回结果
for (r = 0; r < rows; r++)
pOut[r] = pcf[r * columns + columns_1];
free(pcf);
return 0;
}
E. C语言用高斯消元法解n元线性方程
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define NUMBER 20
#define Esc 0x1b
#define Enter 0x0d
float A[NUMBER][NUMBER+1] ,ark;
int flag,n;
void exchange(int r,int k);
float max(int k);
void message();
int main()
{
float x[NUMBER]; /*此数组用于存放方程解*/
int r,k,i,j;
char celect;
system("cls");
printf("\n\n用Gauss列主元消元法解线性方程组");
printf("\n\n1.解方程组请按Enter.");
printf("\n\n2.退出程式请按Esc.");
celect=getch();
if(celect==Esc)
exit(0);
printf("\n\n 输入方程组的维数:n=");
scanf("%d",&n);
printf(" \n\n现在输入系数矩阵A和向量b:");
for(i=1;i<=n;i++)
{
printf("\n\n请输入a%d1--a%d%d系数和向量b%d:",i,i,n,i);
/*实现将每一行中的系数和向量一次性输入,数之间用空格格开,输完后回车确定*/
for(j=1;j<=n+1;j++) /*将刚才输入的数存入数组*/
scanf("%f",&A[i][j]);
}
for(k=1;k<=n-1;k++)
{
ark=max(k);
if(ark==0) /*判断方程是否为线性方程,即是否合法*/
{
printf("\n\n此方程组不合法!");message();
}
else if(flag!=k)
exchange(flag,k);
for(i=k+1;i<=n;i++)
for(j=k+1;j<=n+1;j++)
A[i][j]=A[i][j]-A[k][j]*A[i][k]/A[k][k];
}
x[n]=A[n][n+1]/A[n][n];
for( k=n-1;k>=1;k--)
{
float me=0;
for(j=k+1;j<=n;j++)
{
me=me+A[k][j]*x[j];
}
x[k]=(A[k][n+1]-me)/A[k][k];
}
for(i=1;i<=n;i++)
{
printf(" \n\nx%d=%f",i,x[i]);
}
message();
return 1;
}
void exchange(int r,int k) /*交换行的矩函数*/
{
int i;
for(i=1;i<=n+1;i++)
A[0][i]=A[r][i];
for(i=1;i<=n+1;i++)
A[r][i]=A[k][i];
for(i=1;i<=n+1;i++)
A[k][i]=A[0][i];
}
float max(int k) /*比校系数大小的函数*/
{
int i;
float temp=0;
for(i=k;i<=n;i++)
if(fabs(A[i][k])>temp)
{
temp=fabs(A[i][k]);
flag=i;
}
return temp;
}
void message() /*实现菜单选择的函数*/
{
printf("\n\n 继续运算按 Enter ,退出程式按 Esc!");
switch(getch())
{
case Enter: main();
case Esc: exit(0);
default:{printf("\n\n不合法的输入!");message();}
}
}