使用Fortran计算循环内部

时间:2011-09-08 14:05:06

标签: fortran

我有一些执行模拟的Fortran代码。经过的时间存储在et中,时间步长存储在dt中。两者都被定义为真实的类型。还有另一个实变量tot,它保存模拟运行的最长时间。 i是整数类型的计数变量。我的第一次尝试是这样的:

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-6tot = 100.

3 个答案:

答案 0 :(得分:5)

我不知道这是不是你的错误,因为你没有给整个程序,但在第一个代码中,你做的第一件事就是将et设置为等于dt,因为那时i=1。但是,在第二个代码中,您正在使用et而未设置它(据我们所知)。此外,dt似乎未经初始化使用。如果内存地址et处的字节产生较大的负浮点数,则可能需要更长时间才能达到tot。如果没有更多的代码,那就是我能想到的任何东西。

编辑感谢您的更新。

那么在这种情况下,我认为只需阅读haraldkl的答案,我认为这是你的解决方案。如果你需要通过加100来达到1.0e-6,这对4字节实数不起作用,因为在基数10中只有大约6-7个有意义的数字。你的第一个解决方案稍微好一些,因为你可以用4字节的int达到大约2e9。一种解决方案是使用8字节变量。但是,您应该始终构建一个额外的检查(例如if (et > tot .OR. i > max_iter))以允许最多的迭代,这样您就可以安全地防范这种情况,因为即使您使用整数解决方案,如果您要进行{{ 1}}更大,你的整数可能会溢出,你也会陷入无限循环。

答案 1 :(得分:4)

如果dt相对于tot非常小,那么也可能是在某一点dt如此之小,将其加到,然后大,等没有影响(在数值精度上丢失),因此等等不会超过这一点......

答案 2 :(得分:0)

当您提供部分代码,跳过声明而不是显示错误消息时,您很难得出任何结论,而只是给出您对它们的解释,而很明显,如果您知道如何正确地解释它们,那么您将不会把它们放在第一位。

你的第二个循环与第一个循环的区别在于几个值得注意的事情: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