高斯消元法Fortran90程序
- 格式:doc
- 大小:35.50 KB
- 文档页数:3
fortran90整理1语句编译1.Build—Compile:编译;Build—Build:连接;Build—Exetuce:运⾏;或单击⼯具栏相应按钮。
注意:a、保存⽂件时将⾃动创建同名的project⽂件,形成*.dsp⽂件;b、同时还将⾃动创建同名的workspace,形成*.opt和*.dsw⽂件;c、编译连接后⾃动形成Debug⽬录,该⽬录中存放编译连接后⽂件。
如:*.obj,*.lnk,*.exe等2.Free Format(⾃由格式)1.!感叹号后⾯的⽂本都是注释。
2.每⾏可以编写132个字符。
3.⾏号放在每⾏程序的最前⾯。
4.⼀⾏程序代码的最后如果是符号&,代表下⼀⾏程序会和这⼀⾏连接。
如果⼀⾏程序代码的开头是符号&,代表它会和上⼀⾏程序连接。
3.书写格式⾏的书写(⾏的长度、分⾏、续⾏)1⼀⾏可以是0~132个字符,空格有意义,2语句最长不超过2640个字符3⼀⾏可以有多个语句,⽤“;”分隔4⼀个语句可分⾏写,读⾏标记为&(放在尾部),但如为关键字,⾸尾均加&。
5最多可有511个续⾏。
4.语句的分类注释语句:!后的所有字符都被编译器忽略1.可独占⼀⾏,可在其它语句之后,a)空⾏为注释⾏(固定格式⽤C和*)2.说明语句:⽤于说明变量的类型、属性等3.可执⾏语句:输⼊、赋值、输出……5.语句有位置规定:说明语句必须出现在可执⾏语句之前,格式说明语句(FORMAT语句)除外。
6.标志符⼩结注释标志符:1⾃由格式:!固定格式:C *2语句分隔符:分号;(仅⾃由格式可以使⽤)3续⾏符:⾃由格式:&4申明标号:1到5位⽆符号整数5空格:关键字、变量、常量内部不能⽤空格,但相邻两者之间须⽤空格6.FORTRA90源程序基本结构1、FORTRAN90程序是⼀种分块结构,由若⼲个程序单元块组成:主程序、外部⼦程序、模块、块数据单元⽆论是主程序单元,还是⼦程序单元,都是独⽴的程序单位,应该独⽴编写,它们的形式相似。
本文末给出Gauss-Jordan消去法的Fortran90源程序。
!/************************************************************* !程序:Gauss_Jordan消去法!过程:Gauss_Jordan(aa,b,n,sgn)!作用:aa为方阵,b为aa的逆,n为aa的阶! sgn为标识符,1表示求逆成功,0表示求逆失败!调用格式为:call Gauss_Jordan(aa,b,n,sgn)!*************************************************************/ subroutine Gauss_Jordan(aa,b,n,sgn)implicit noneinteger(4):: n,sgnreal(8):: aa(n,n),b(n,n)integer(4):: i,j,kreal(8),allocatable:: a(:,:)real(8):: tallocate(a(n,n))a=aa ! a代替aa进行运算sgn=1! 初始化b为单位阵do i=1,ndo j=1,nif(i==j) thenb(i,j)=1elseb(i,j)=0end ifend doend do! Gauss_Jordan消去法过程do k=1,nif(a(k,k)==0) thensgn=0;EXITend if! 化第k行使得a(k,k)为1t=1.0d0/a(k,k)do j=k,na(k,j)=a(k,j)*tend dodo j=1,nb(k,j)=b(k,j)*tend do! 完成第k列的计算do i=1,nif(i/=k)thent=a(i,k)do j=k,na(i,j)=a(i,j)-a(k,j)*tend dodo j=1,nb(i,j)=b(i,j)-b(k,j)*tend doend ifend doend doend subroutine Gauss_Jordanprogram equation_solveimplicit noneinteger n,sgnparameter(n=2)real tinteger i,j,kreal aa(n,n),b(n,n),c(n,1),x(n,1)real,allocatable:: a(:,:)read*,aa,callocate(a(n,n))a=aa ! a代替aa进行运算sgn=1! 初始化b为单位阵do i=1,ndo j=1,nif(i==j) thenb(i,j)=1elseb(i,j)=0end ifend doend do! Gauss_Jordan消去法过程do k=1,nif(a(k,k)==0) thensgn=0EXITend if! 化第k行使得a(k,k)为1t=1.0/a(k,k)do j=k,na(k,j)=a(k,j)*tend dodo j=1,nb(k,j)=b(k,j)*tend do ! 完成第k列的计算do i=1,nif(i/=k)thent=a(i,k)do j=k,na(i,j)=a(i,j)-a(k,j)*tend dodo j=1,nb(i,j)=b(i,j)-b(k,j)*tend doend ifend doend dox=matmul(b,c)write(*,20) ((b(i,j),j=1,n),i=1,n)20 format(5X,2F9.3)write(*,10) (x(i,1),i=1,n)10 format(5X,F5.3)end!正确的编程,但是需要能求得出逆矩阵的矩阵方程! write(*,20) ((b(i,j),j=1,n),i=1,n)! 20 format(5X,2F9.3) !print*," aa的逆矩阵 ",b !x=matmul(b,c)!write(*,10) (x(i,1),i=1,n)!10 format(5X,F5.3) !print*," aa的逆矩阵 ",b !end。
FORTRAN语言课程设计摘要:科技的日新月异使得计算机领域不断取得新的研究成果。
计算机在代替和延伸脑力劳动方面发挥越来越重要的作用,不仅在工业方面而且在日常生活和科研中也越来越离不开计算机。
特别是在天体运动方面需要运用到计算机处理大量的数据。
这次我选的实践课题是用Jacobi迭代和Gauss-Seidel迭代法求解线性方程组AX=B,这其中涉及的就是天体运动的轨迹问题,我利用从FORTRAN 90中学到的迭代、循环、子程序等知识设计程序,通过Fortran PowerStation 4.0进行运行、调试,不得不提的是QuickWin,它在绘制行星的运动轨迹上发挥出了相当大的贡献。
通过这次的实践我从中充分体会到了Fortran语言接近数学公式的自然描述,在计算机里具有很高的执行效率的最大特性。
同时我也看到了Fortran语言是一种极具发展潜力的语言,在数值计算中,Fortran语言仍然不可替代。
Fortran90标准引入了数组计算等非常利于矩阵运算的功能。
在数组运算时,Fortran能够自动进行并行运算,这是很多编程语言不具备的。
运用Fortran 语言,你能够运用很多现成的函数软件包,所以非常便利。
关键词:Fortran ;Jacobi迭代和Gauss-Seidel迭代;天体运动1设计思想这次的课程设计我选的是第三个课题,关于求解天体的运行轨道,原题如下:●用Jacobi迭代和Gauss-Seidel迭代法求解线性方程组AX=b。
一天文学家要确定一颗小行星绕太阳运行的轨道,他在轨道平面内建立以太阳为原点的直角坐标系,在五个不同的点对小行星作了五次观察,测得轨道上五个点的坐标数据(单位:万公里)如下表所示:由开普勒第一定律知,小行星轨道为一椭圆,椭圆的一般方程可表示为:a1x2+2a2xy+a3y2+2a4x+2a5y+1=0分别将五个点的数据代入椭圆一般方程中,得到线性方程组,求出待定系数a1,a2,a3,a4,a5。
Fortran90均匀和正态(⾼斯)分布随机数⽣成程序module ran_mod! module contains four functions! ran1 and ran2 return a uniform random number between 0-1! normal1 and normal 2 return a normal distributioncontainsfunction ran1() !returns random number between 0 - 1implicit noneinteger :: flagdouble precision :: ran1save flagdata flag /0/if(flag==0) thencall random_seed(); flag = 1endifcall random_number(ran1) ! built in fortran 90 random number function returnend function ran1function ran2(idum)implicit noneinteger, parameter :: IM1=2147483563, IM2=2147483399integer, parameter :: IMM1=IM1-1, IA1=40014, IA2=40692integer, parameter :: IQ1=53668, IQ2=52774, IR1=12211, IR2=3791integer, parameter :: NTAB=32, NDIV=1+IMM1/NTABinteger, dimension (NTAB) :: ivinteger :: idum, idum2, iy, i, j, kdouble precision, parameter :: EPS=1.2D-7, RNMX=1.d0-EPS, AM=1.d0/IM1double precision :: ran2, RNMKsave iv, iy, idum2data idum2/123456789/, iv/NTAB*0/, iy/0/if(idum.le.0)thenidum = max(-idum,1)idum2 = idumdo j = NTAB+8,1,-1k = idum/IQ1idum = IA1*(idum-k*IQ1)-k*IR1if(idum.lt.0) idum = idum + IM1if(j.le.NTAB) iv(j) = idumend doiy = iv(1)end ifk = idum/IQ1idum = IA1*(idum-k*IQ1)-k*IR1if(idum.lt.0) idum = idum + IM1k = idum2/IQ2idum2 = IA2*(idum2-k*IQ2)-k*IR2if(idum2.lt.0) idum2 = idum2 + IM2j = 1+iy/NDIViy = iv(j)-idum2iv(j) = idumif(iy.lt.1) iy = iy + IMM1ran2 = min(AM*iy,RNMX)returnend functionfunction normal1(mean,sigma) !returns a normal distribution implicit noneinteger :: flagdouble precision :: normal1, tmp, mean, sigmadouble precision :: fac, gsave, rsq, r1, r2save flag, gsavedata flag /0/if (flag.eq.0) thenrsq=2.0d0do while(rsq.ge.1.0d0.or.rsq.eq.0.0d0) ! new from for dor1 = 2.0d0 * ran1() - 1.0d0r2 = 2.0d0 * ran1() - 1.0d0rsq = r1 * r1 + r2 * r2enddofac = sqrt(-2.0d0*log(rsq)/rsq)gsave = r1 * factmp = r2 * facflag = 1elsetmp = gsaveflag = 0endifnormal1 = tmp * sigma + meanreturnend function normal1function normal2(mean,sigma)implicit noneinteger :: flagdouble precision, parameter :: pi = 3.141592653589793239double precision :: u1, u2, y1, y2, normal2, mean, sigmasave flagdata flag /0/u1 = ran1(); u2 = ran1()if (flag.eq.0) theny1 = sqrt(-2.0d0*log(u1))*cos(2.0d0*pi*u2)normal2 = mean + sigma*y1flag = 1elsey2 = sqrt(-2.0d0*log(u1))*sin(2.0d0*pi*u2)normal2 = mean + sigma*y2flag = 0endifreturnend function normal2end module ran_modThe above codes are made in Fortran 90 language, if you have any question, you may write to sealin2008@/doc/d6ddff43336c1eb91a375daa.html。
!JACOBI迭代求解方程组program jacobiimplicit noneinteger :: i,jinteger :: k !迭代次数旗标save kreal,parameter :: e=0.001integer,parameter :: n=4real :: x(n),y(n),b(n)data b /1.38,-0.34,0.67,1.52/real :: Dreal :: a(n,n)!!!千万千万要注意Fortran的数据存放是按照列来存放的,如果变成还按照习惯的数组存放方式输入数据,会导致错误!!!data a /2.52,0.39,0.55,0.23,0.95,1.69,-1.25,-1.15,1.25,-0.45,1.96,-0.45,-0.85,0.49,-0.98,2.31/ write(*,*)"*********矩阵A的形式为*********"write(*,"(1x,4f6.2,/)")aforall(i=1:n)x(i)=0end forallk=1100 D=0do i=1,ny(i)=b(i)do j=1,nif(i/=j) y(i)=y(i)-a(i,j)*x(j)end doy(i)=y(i)/a(i,i)end dodo j=1,nD=abs(x(j)-y(j))end doforall(i=1:n)x(i)=y(i)end forallif(D>=e) thenk=k+1write(*,*)"迭代次数为:",kgoto 100elsegoto 200end if200 write(*,*)"*************************************"write(*,*)"用jacobi方法解得的结果X[t]为:"write(*,"(1x,4f6.2,/)")x(:)stopend program*******************************************************************************!GAUSS-SEIDEL迭代求解方程组program jacobiimplicit noneinteger :: i,jinteger :: k !迭代次数旗标save kreal,parameter :: e=0.001integer,parameter :: n=4real :: x(n),y(n),b(n)data b /1.38,-0.34,0.67,1.52/real :: Dreal :: a(n,n)!!!千万千万要注意Fortran的数据存放是按照列来存放的,如果变成还按照习惯的数组存放方式输入数据,会导致错误!!!data a /2.52,0.39,0.55,0.23,0.95,1.69,-1.25,-1.15,1.25,-0.45,1.96,-0.45,-0.85,0.49,-0.98,2.31/ write(*,*)"*********矩阵A的形式为*********"write(*,"(1x,4f6.2,/)")aforall(i=1:n)x(i)=0end forallk=1100 D=0do i=1,ny(i)=b(i)do j=1,nif(i<j) y(i)=y(i)-a(i,j)*x(j)if(i>j) y(i)=y(i)-a(i,j)*y(j)end doy(i)=y(i)/a(i,i)end dodo j=1,nD=abs(x(j)-y(j))end doforall(i=1:n)x(i)=y(i)end forallif(D>=e) thenk=k+1write(*,*)"迭代次数为:",kgoto 100elsegoto 200end if200 write(*,*)"*************************************"write(*,*)"用Gauss-seidel方法解得的结果X[t]为:"write(*,"(1x,4f6.2,/)")x(:)write(*,*)"由运行结果可以看出,运算量G-S比JACOBI少至少一倍"stopend programimplicit nonesubroutine gauss(a,b,n,x,l,js)dimension a(n,n),x(n),b(n),js(n) double precision a,b,x,t l=1do k=1,n-1 d=0.0do i=k,ndo j=k,nif(abs(a(i,j)).gt.d)then d=abs(a(i,j)) js(k)=j is=iEndifend doif(d+1.0.eq.1.0)then l=0else if(js(k).ne.k)thendo i=k,n t=a(i,k) a(i,k)=a(i,js(k)) a(i,js(k))=tend doendifif(is.ne.k)thendo j=k,n t=a(k,j) a(k,j)=a(is,j) a(is,j)=tend do t=b(k) b(k)=b(is) b(is)=tendifendifif(l.eq.0)then write(*,100)endifdo j=k+1,n a(k,j)=a(k,j)/a(k,k)end do b(k)=b(k)/a(k,k)do i=k+1,ndo j=k+1,n a(i,j)=a(i,j)-a(i,k)*a(j,k)end do b(i)=b(i)-a(i,k)*b(k)end doend do if(abs(a(n,n))+1.0.eq.1.0)then l=0 write(*,100)end if x(n)=b(n)/a(n,n)do i=n-1,1,-1 t=0.0do j=i+1,n t=t+a(i,j)*x(j)end do x(i)=b(i)-tend do 100 format(1x,'fall') js(n)=ndo k=n,1,-1if(js(k).ne.k)then t=x(k) x(k)=x(js(k)) x(js(k))=t end if end doend do。
高斯消元法程序一、引言高斯消元法是一种求解线性方程组的常用方法,通过将线性方程组转化为行阶梯形矩阵,进而求得方程组的解。
本文将介绍高斯消元法的原理和实现过程,并给出一个简单的高斯消元法的程序示例。
二、高斯消元法原理高斯消元法的核心思想是通过矩阵的初等行变换,将线性方程组转化为行阶梯形矩阵,进而求解方程组的解。
具体的步骤如下:1. 构造增广矩阵:将线性方程组的系数矩阵和常数向量合并成一个增广矩阵。
2. 第一步消元:通过初等行变换,使得增广矩阵的第一列除第一个元素外的其他元素都变为0。
3. 逐列消元:对于增广矩阵的每一列(除第一列外),重复以下步骤:a. 找到当前列中第一个非零元素所在的行,并将该行交换到当前列的第一行。
b. 通过初等行变换,使得当前列的第一个元素下方的所有元素都变为0。
4. 回代求解:从最后一行开始,逐步回代求解出方程组的解。
三、高斯消元法程序示例下面给出一个简单的高斯消元法的程序示例,该程序使用C语言编写:```c#include <stdio.h>#define N 3 // 方程组的未知数个数void gauss_elimination(double A[N][N+1], double x[N]) { int i, j, k;double factor, tmp;// 第一步消元for (i = 0; i < N; i++) {factor = A[i][i];for (j = i; j < N + 1; j++) {A[i][j] /= factor;}for (k = i + 1; k < N; k++) {factor = A[k][i];for (j = i; j < N + 1; j++) {A[k][j] -= factor * A[i][j];}}}// 回代求解for (i = N - 1; i >= 0; i--) { tmp = 0;for (j = i + 1; j < N; j++) { tmp += A[i][j] * x[j]; }x[i] = A[i][N] - tmp;}}int main() {double A[N][N+1] = {{2, 1, -1, 8},{-3, -1, 2, -11},{-2, 1, 2, -3}};double x[N];int i;gauss_elimination(A, x);printf("方程组的解为:\n"); for (i = 0; i < N; i++) {printf("x[%d] = %f\n", i, x[i]);}return 0;}```程序中,`gauss_elimination`函数实现了高斯消元法的过程,`main`函数中给出了一个包含3个未知数的线性方程组的示例,程序输出了方程组的解。
本文末给出Gauss-Jordan消去法的Fortran90源程序。
!/************************************************************* !程序:Gauss_Jordan消去法
!过程:Gauss_Jordan(aa,b,n,sgn)
!作用:aa为方阵,b为aa的逆,n为aa的阶
! sgn为标识符,1表示求逆成功,0表示求逆失败
!调用格式为:call Gauss_Jordan(aa,b,n,sgn)
!*************************************************************/ subroutine Gauss_Jordan(aa,b,n,sgn)
implicit none
integer(4):: n,sgn
real(8):: aa(n,n),b(n,n)
integer(4):: i,j,k
real(8),allocatable:: a(:,:)
real(8):: t
allocate(a(n,n))
a=aa ! a代替aa进行运算
sgn=1
! 初始化b为单位阵
do i=1,n
do j=1,n
if(i==j) then
b(i,j)=1
else
b(i,j)=0
end if
end do
end do
! Gauss_Jordan消去法过程
do k=1,n
if(a(k,k)==0) then
sgn=0;EXIT
end if
! 化第k行使得a(k,k)为1
t=1.0d0/a(k,k)
do j=k,n
a(k,j)=a(k,j)*t
end do
do j=1,n
b(k,j)=b(k,j)*t
end do
! 完成第k列的计算
do i=1,n
if(i/=k)then
t=a(i,k)
do j=k,n
a(i,j)=a(i,j)-a(k,j)*t
end do
do j=1,n
b(i,j)=b(i,j)-b(k,j)*t
end do
end if
end do
end do
end subroutine Gauss_Jordan
program equation_solve
implicit none
integer n,sgn
parameter(n=2)
real t
integer i,j,k
real aa(n,n),b(n,n),c(n,1),x(n,1)
real,allocatable:: a(:,:)
read*,aa,c
allocate(a(n,n))
a=aa ! a代替aa进行运算
sgn=1
! 初始化b为单位阵
do i=1,n
do j=1,n
if(i==j) then
b(i,j)=1
else
b(i,j)=0
end if
end do
end do
! Gauss_Jordan消去法过程
do k=1,n
if(a(k,k)==0) then
sgn=0
EXIT
end if
! 化第k行使得a(k,k)为1
t=1.0/a(k,k)
do j=k,n
a(k,j)=a(k,j)*t
end do
do j=1,n
b(k,j)=b(k,j)*t
end do ! 完成第k列的计算
do i=1,n
if(i/=k)then
t=a(i,k)
do j=k,n
a(i,j)=a(i,j)-a(k,j)*t
end do
do j=1,n
b(i,j)=b(i,j)-b(k,j)*t
end do
end if
end do
end do
x=matmul(b,c)
write(*,20) ((b(i,j),j=1,n),i=1,n)
20 format(5X,2F9.3)
write(*,10) (x(i,1),i=1,n)
10 format(5X,F5.3)
end
!正确的编程,但是需要能求得出逆矩阵的矩阵方程
! write(*,20) ((b(i,j),j=1,n),i=1,n)
! 20 format(5X,2F9.3) !print*," aa的逆矩阵 ",b !x=matmul(b,c)
!write(*,10) (x(i,1),i=1,n)
!10 format(5X,F5.3) !print*," aa的逆矩阵 ",b !end。