Variables 辛普森&x27;s规则,不接受用户请求输入的声明?fortran
我正在研究这个问题,用辛普森法则得到棕褐色曲线下的面积。然而,我不断地得到我不理解的错误——即使是在不同的编译器上,比如gfortran和ifort 我意识到我可以在程序的主体中把pi作为一个参数,但我更愿意找出哪里出了问题。任何帮助都将不胜感激Variables 辛普森&x27;s规则,不接受用户请求输入的声明?fortran,variables,fortran,integration,Variables,Fortran,Integration,我正在研究这个问题,用辛普森法则得到棕褐色曲线下的面积。然而,我不断地得到我不理解的错误——即使是在不同的编译器上,比如gfortran和ifort 我意识到我可以在程序的主体中把pi作为一个参数,但我更愿意找出哪里出了问题。任何帮助都将不胜感激 module consts !Declare pi as a global variable real(4),parameter :: pi=3.1415927 end module PROGRAM simpson
module consts
!Declare pi as a global variable
real(4),parameter :: pi=3.1415927
end module
PROGRAM simpson
use consts
implicit none
REAL :: area, h, sumo, sume
INTEGER (kind=4) :: i, j, k !Loop index, Counter, Number of points
REAL (kind=4) :: rad, TanTab(0) !Radian variable to be calculated in Subroutine, Result array
!k = number of steps
WRITE(6,*) "Please enter number of steps required (odd number)"
READ(5,*) k
IF(MOD(k,2) == 1) THEN
CONTINUE
ELSE
WRITE(*,*) "Hey, I said as an odd number"
READ(5,*) k
ENDIF
h = (60.0)/(k-1) ! Defining step size in relation to number of sampling points
DO i=1,61,1
! Get table of tan
call degtorad((i-1)*1.0, rad)
TanTab(j) = tan(rad)
j=j+1
write(*,*) "Tan(", i, ")", TanTab(i)
write(*,*) "Tan(", j, ")", TanTab(j)
ENDDO
DO j=1,k-1,h
IF(MOD(k,2) == 1) THEN
sumo = sumo + TanTab(j) !sum of odd functions
ELSE
sume = sume + TanTab(j) !sum of even functions
area = (h/3)*( (4*sumo) + (2*sume) + tan(1.047))
WRITE(6,*) area
ENDIF
ENDDO
END PROGRAM simpson
我可以看到运行时崩溃的一个可能原因,即引发分段冲突: 在行中使用
j
TanTab(j) = tan(rad)
在为其赋值之前。Fortran不自动初始化变量
我也能看到一些非常可疑的东西。您将tantab
声明为具有维度0
:
REAL (kind=4) :: rad, TanTab(0)
现在Fortran可以很高兴地访问数组中声明边界以外的元素,有时(有时是很长一段时间)程序的用户不会注意到这个问题。如果您使用选项-检查边界(这是英特尔版本,其他编译器也有相同的功能,请参阅您的文档)编译代码,然后尝试运行代码,则会出现运行时错误
我同意@AlexanderVogt(我通常是这样)关于循环索引使用实变量的观点。不要这样做。一些需要考虑的事情:循环doi=1,61,1
建议您应该设置TanTab(i)
,而不是TanTab(j)
。为什么还要费心处理另一个变量j
,它会像i
那样递增?由于循环从1到61,因此建议您将TanTab
声明为real,dimension(1:61)::TabTab
,否则它将不足以存储值。但是你的下一个循环,doj=1,k-1,h
是不同的。您确定它正在以一致的方式访问选项卡(j)
?您的代码中有更多错误:
- 在计算h时,使用的是degs而不是rads
- TanTab数组中与项数有关的积分上界
- 不将变量初始化为0(sumo、sume等)
- 每个步骤的面积计算,可在do循环外完成
- 越界错误
您应该开始使用调试器,并学习如何在代码中查找问题。工作版本如下:
PROGRAM simpson
implicit none
REAL :: area, h, sumo, sume
INTEGER (kind=4) :: i!Loop index
integer, parameter :: k = 100
REAL (kind=4) :: rad, TanTab(k+1) !Radian variable to be calculated in Subroutine, Result array
sumo = 0.0
sume = 0.0
area = 0.0
h = 0.0174532925 * 60.0/real(k) ! Defining step size in relation to number of sampling points
DO i=1,k+1
rad = 0.0174532925 * 60.0 * real(i-1) /real(k)
TanTab(i) = tan(rad)
! write(*,*) "Tan(", i-1, ")", TanTab(i)
ENDDO
DO i=2,k
IF(MOD(i,2) == 1) THEN
sumo = sumo + TanTab(i) !sum of odd functions
ELSE
sume = sume + TanTab(i) !sum of even functions
ENDIF
ENDDO
! by simson
area = (h/3)*( TanTab(1) + (2*sume) + (4*sumo) + TanTab(k+1))
WRITE(*,*) area
! by integration
area = log(1.0) - log(cos(0.0174532925 * 60.0))
WRITE(*,*) area
END PROGRAM simpson
您会遇到什么错误?您的步长h
是真实的
!这可能会导致巨大(且难以发现)的错误。请仅对循环计数器使用integer
s。。。另外,注意混合real
s和integer
s(如h=(60.0)/(k-1)
)-这可能不是您想要的方式。这是您自己写的还是“查找bug”的家庭作业问题?在许多问题中,您的最终写入将永远不会遇到,因为它的内部if k偶数
构造,而向上(某种尝试)确保k是奇数。还有为什么要在第一个循环中硬编码61呢?嗨,乔治,我自己写的-只是在一本书中处理一些问题,所以我使用了我在其他问题中写的一些代码片段。很明显,关于混合变量,我还有很多需要学习的地方,在尝试使用和操作真实变量时,我会犯一些简单的错误,比如写1而不是1.0。我现在已经学到了在循环中使用reals的经验。有人能推荐一个好的fortran调试器吗?我从我的英特尔编译器中获得了源代码级错误信息,但肯定还有更重要的内容?谢谢,我声明它的维数为1,并在do循环之前为j赋值,但现在,即使它正在编译,在我为输入输入奇数后,它不会打印任何结果?当代码清楚地表明您想要创建一个切线值表时,给TanTab
一个1
维度与给它一个0
维度一样错误。为什么不将数组声明为具有正确的大小或具有可在运行时设置的大小?我不会再评论了。如果需要进一步输入,请编辑问题以反映更新的问题。看在Knuth的份上,确切地告诉我们您正在经历什么错误消息或异常行为。Grand,它不再吐出任何错误,它只是在请求输入并允许我输入后运行时退出—正如刚才所述。我对维度的概念感到困惑,我试着用2表示一张表,试着用62表示步数——每次都是同样的问题。除了我自己的学习,我什么都不用做,所以不用担心,谢谢你的时间。如果你要发布一个工作版本,为什么不发布一个好的呢?。拾取nits(i)log(1.0)
总是0
,那么为什么还要麻烦(ii)您声明了k
real,然后将其(real(k)
)强制转换几次,并且通常将其当作一个整数来使用(iii)常量,例如0.0174532925*60.0
,都是很好的参数声明候选者。可能还有其他问题。代码的工作原理是,你可以得到积分的合理近似值,它清楚地显示了原始问题中的所有错误。对于您的评论i)这不是一个生产代码,但显示了背后的数学。即使log(1.0)是0,它更能解释那里发生了什么ii)我把k声明为int(如问题中所述),但忘了我后来把它改成了real iii)和I)一样,它清楚地显示了deg->rad转换,对于理解代码来说,哪一个更好。比较一下Simpson规则和集成规则的实现是很好的。好消息是我理解了您所写的内容,这将有助于防止我再次出现简单错误。@user3311029我很高兴它有所帮助。请记住,当您编写新代码时,找到一些方法来检查代码是否正常工作总是很好的