我有一些执行模拟的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-6
和tot = 100.
答案 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