使用Fortran进行循环内计数
我有一些执行模拟的Fortran代码。所用时间存储在et
中,时间步存储在dt
中。两者都被定义为真实类型。还有一个实际变量tot
,它保存了模拟应该运行的最长时间。 i
是整数类型的计数变量。我第一次尝试是这样的:使用Fortran进行循环内计数
real, intent(in) :: dt
real, intent(in) :: tot
real :: et
integer :: i
et = 0.0
i = 0
do
i = i+1
et = real(i)*dt
if (et > tot) exit
! main code here
end do
我想摆脱i
,因为它是在一个地方只用,但是,当我尝试这样做,程序时的总时间是大挂起:
real, intent(in) :: dt
real, intent(in) :: tot
real :: et
et = 0.0
do
et = et + dt
if (et > tot) exit
! main code here
end do
导致程序响应如此不同的两个代码示例有什么不同?我的编译器是g77。
编辑:我已经将声明和初始化添加到上面的代码示例。
编辑2:传递给子程序的初始值是dt = 1e-6
和tot = 100.
我不知道这是不是你的错误,因为你不给整个程序,但在第一个代码,第一你做的事情是设置et
等于dt
,因为在那一点i=1
。然而,在第二个代码中,您正在使用et
而没有设置它(据我们所能猜到)。另外,dt
似乎被使用未初始化。如果内存地址为et
的字节会产生大的负值浮动,则可能需要更长的时间才能达到tot
。就我所能想象的而言,没有更多的代码。
编辑感谢您的更新。
那么在这种情况下,我认为刚刚阅读哈拉尔克的答案,我认为这是你的解决方案。如果您需要通过合并1.0e-6
来达到100
,则这不适用于4字节的真实数据,因为在基数10中只有大约6-7个有意义的数字。您的第一个解决方案略好,因为您可以达到大约2e9与一个4字节的int。一种解决方案是使用8字节变量。然而,你应该总是建立一个额外的检查(例如if (et > tot .OR. i > max_iter)
)以允许最大的迭代,所以你可以安全地防止这种情况,因为即使你使用整数解决方案,如果你想增大tot
,你的整数可能会溢出,你也会陷入无限循环。
查看上面的修改。对不起,我忽略了在我原来的问题中包含初始化。 – astay13
当你给出部分代码,跳过声明,而不是显示错误消息,你只是给你的解释,而很明显,如果你知道如何正确解释它们,你不会让他们摆在首位。
你的第二个循环与第一个循环的区别在于以下几点值得注意:a)循环开始时变量的值是什么,b)循环计数器是什么,c)是实数还是整数? ......等等
以下是这些循环可以写成
program various_do_loops
integer :: i
real :: et, tot, dt
! DO WHILE LOOP (whoops, I just now see you're using g77
! so this may or may not work)
i = 0
et = 0.
tot = 10.
dt = 1.
do while (et<tot)
i = i+1
et = real(i)*dt
! main code goes here
! ....
! ....
write(*,'("et is currently ", f5.2)')et
end do
! Old kind of WHILE LOOP
i = 0
et = 0.
tot = 10.
dt = 1.
10 if(et<tot) then
i = i + 1
et = real(i)*dt
! main code goes here
! ....
! ....
write(*,'("et is currently ", f5.2)')et
goto 10
end if
end program various_do_loops
请参阅上面的编辑初始化/声明。完整的代码足够大,以至于发布都不切实际。请注意,没有错误消息,我只是偶然注意到,使用循环计数的一种策略,程序运行时间显着延长,并且想要了解其原因。 – astay13
程序如何挂起?错误?无限循环(即'等'永远不会达到'tot')? –
@Anders:我假设一个无限循环,因为程序运行10分钟以上而不停止(使用代码的第一个版本,大约1.5分钟后停止)。 – astay13
我猜'et'会在主代码里面重新定义。您是否尝试过打印这些值以检查其行为是否符合您的期望? –