Fortran 为什么第二个if子句还要执行呢?

Fortran 为什么第二个if子句还要执行呢?,fortran,Fortran,我的程序中有一个do-while循环,谁的条件是继续,他总是给我一个错误,我不知道为什么。看起来是这样的: do while (ii .le. nri .and. ed(ii) .le. e1) ! do some stuff... ii = ii + 1 end do 其中ii和nri是标量整数,e1是标量实数,ed是长度nri的实数数组。我期望在上次运行后发生的是,因为ii.le.nri返回.false.第二个条件从未被测试过,并且我不会因为一个问题而得到任何好处。我已经用

我的程序中有一个
do-while
循环,谁的条件是继续,他总是给我一个错误,我不知道为什么。看起来是这样的:

do while (ii .le. nri .and. ed(ii) .le. e1)
    ! do some stuff...
    ii = ii + 1
end do
其中
ii
nri
是标量整数,
e1
是标量实数,
ed
是长度
nri
的实数数组。我期望在上次运行后发生的是,因为
ii.le.nri
返回
.false.
第二个条件从未被测试过,并且我不会因为一个问题而得到任何好处。我已经用调试器验证了
ii.le.nri
确实返回了
.false.
——但是程序崩溃了

为了验证我只测试一个条件的假设,我甚至编写了一个小测试程序,我使用相同的编译器选项编译了该程序:

 program iftest
     implicit none

     if (returns_false() .and. returns_true()) then
         print *, "in if block"
     end if
 contains
     function returns_true()
         implicit none
         logical returns_true
         print *, "in returns true"
         returns_true = .true.
     end function

     function returns_false()
         implicit none
         logical returns_false
         print *, "in returns false"
         returns_false = .false
     end function
 end program
正如我所料,运行这个程序只会输出

 $ ./iftest
 in returns false
和出口。第二个测试永远不会运行


为什么这不适用于我的
do while
子句?

与某些语言不同,Fortran不保证复合逻辑表达式的任何特定求值顺序。对于代码,在最后一次循环while循环时,
ii
的值设置为
nri+1
。与某些语言相比,编译器生成的代码测试
ed(nri+1)是合法的。Fortran不保证复合逻辑表达式的任何特定求值顺序。对于代码,在最后一次循环while循环时,
ii
的值设置为
nri+1
。编译器生成测试
ed(nri+1)扩展答案高性能标记的代码是合法的,以下是重写循环的一种方法:

ii_loop: do

  if (ii .gt. nri) exit ii_loop
  if (ed(ii) .gt. e1) exit ii_loop

  ! do some stuff

  ii = ii + 1

end do ii_loop

扩展answer High Performance标记,以下是重写循环的一种方法:

ii_loop: do

  if (ii .gt. nri) exit ii_loop
  if (ed(ii) .gt. e1) exit ii_loop

  ! do some stuff

  ii = ii + 1

end do ii_loop

当ii==nri时,将对第二个条件进行测试,因为您在第二个条件下测试可能会导致问题的浮动,不是吗?@kels1986:True-这也是我必须解决的问题。但是,在这个例子中,我已经用调试器验证了这不是问题所在;当
ii==nri
,而不是在下一次运行时(这将是比较reals的问题),程序会因一个错误而崩溃。@Kells1986:另一方面(经过一点思考):reals的相对差值总是在10^-4左右,我使用的是64位实数-这永远不会出现舍入错误问题。当ii==nri时,第二个条件将被测试,因为你在第二个条件下测试的浮点值可能会导致问题,不是吗?@Kells1986:True-这也是我必须解决的问题。但是,在这个例子中,我已经用调试器验证了这不是问题所在;当
ii==nri
,而不是在下一次运行时(这将是比较reals的问题),程序会因一个错误而崩溃。@Kells1986:另一方面(经过一点思考):reals的相对差值总是在10^-4左右,我使用的是64位实数-这永远不会出现舍入错误问题。哈哈,又一个Fortran gotcha=)正如你在过去几周里回答我的许多问题时所注意到的,我在这方面还是个新手。使用数组边界检查进行编译是我发现这是一个错误的原因,所以这就是我已经在做的事情
-O0
也没有改变任何东西,但是如果标准中没有定义检查顺序,我想这并不奇怪。我应该如何将我的大脑逻辑放入编译器实际使用的一组指令中?=)Fortran是一种非常容易使用的编程语言(当然对于我们这些有30年经验的人来说),但对于那些已经因为接触其他(因此较少)语言而心烦意乱的人来说,使用Fortran可能有点困难。Fortran是一个外国,我们在这里的想法是不同的。尝试ed(min(ii,nri))作为一个简单的解决方案,看看这是否真的是问题所在。哈哈,还有一个Fortran gotcha=)正如你在过去几周里回答我这么多问题时所注意到的,我在这方面还是个新手。使用数组边界检查进行编译是我发现这是一个错误的原因,所以这就是我已经在做的事情
-O0
也没有改变任何东西,但是如果标准中没有定义检查顺序,我想这并不奇怪。我应该如何将我的大脑逻辑放入编译器实际使用的一组指令中?=)Fortran是一种非常容易使用的编程语言(当然对于我们这些有30年经验的人来说),但对于那些已经因为接触其他(因此较少)语言而心烦意乱的人来说,使用Fortran可能有点困难。Fortran是一个陌生的国家,我们在这里确实有不同的想法。尝试ed(min(ii,nri))作为一个简单的修复,看看这是否真的是问题所在。为什么不简单的
do ii=iista,nri
检查一下里面的
ed(ii)
或其他东西呢?是的,这也会起作用。可能更简单。如果。。退出
ed(ii)
测试,或者让代码在
IF
块中执行。为什么不做一个简单的
do ii=iista,nri
,检查
ed(ii)
内部或其他东西?是的,这也会起作用。可能更简单。如果。。退出
ed(ii)
测试的
,或在
IF
块中执行代码。