2013-04-22 57 views
1

我在我的程序中有一个do while循环,谁的条件继续不断给我一个一个的错误,我不明白为什么。它看起来像这样:为什么第二个if-clause甚至执行?

do while (ii .le. nri .and. ed(ii) .le. e1) 
    ! do some stuff... 
    ii = ii + 1 
end do 

其中iinri是标量整数,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子句?

+0

当II == NRI那么第二个条件将受到考验,因为你要在第二个状态测试花车那可能会导致问题不可能吗? – James 2013-04-22 17:43:05

+0

@ Kells1986:是的 - 这也是我必须解决的问题。然而,在这种情况下,我已经用调试器验证过这不是问题;当'ii == nri'时,程序崩溃时出现错误的错误,而不是下一次运行(这将是比较实数的问题)。 – 2013-04-22 18:37:16

+0

@ Kells1986:另一方面(在对此事进行了一些思考之后):实数总是会有大约10^-4的相对差异,我使用的是64位实数 - 这绝不应该受四舍五入错误问题影响。 – 2013-04-22 19:19:17

回答

6

与某些语言相比,Fortran并不保证对复合逻辑表达式进行任何特定的评估顺序。在你的代码的情况下,在最后的while循环中,ii的值被设置为nri+1。您的编译器生成的代码测试ed(nri+1)<=e1并因此引用ed范围之外的元素是合法的。这可能是您程序崩溃的原因。

您的期望与该语言的Fortran标准规定相反。

如果您尚未这样做,请尝试重新编译您的代码,并打开数组边界检查并查看会发生什么。

至于为什么你的测试没有排除这个问题,那么我怀疑你的所有测试真的表明你的编译器为不同的条件产生了不同的执行顺序,对等的。

+0

哈哈,又一个Fortran陷阱=)正如你在过去几周回答很多问题时所注意到的那样,我在这方面很新颖。编译时使用数组边界检查是我发现这是一个错误的原因,所以这就是我已经做的。'-O0'也没有改变任何东西,但如果检查的顺序在标准中是未定义的,我想这并不奇怪。我应该如何将我的大脑逻辑放入编译器实际使用的一组指令中? =) – 2013-04-22 18:40:29

+2

Fortran是一种非常易于使用的编程语言(当然,对于我们这些拥有30年经验的人),虽然对于那些接触到其他语言(因此较少)的语言已经感到不安的人来说,它可能有点困难。 Fortran是一个外国国家,我们在这里有不同的看法。 – 2013-04-23 08:22:32

+0

尝试ed(min(ii,nri))作为一个简单的修复,看看这是否确实是问题。 – agentp 2013-04-23 18:58:20

4

扩展答案高性能马克,这里是重写循环的一种方法:

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 
+0

为什么不用一个简单的''do ii = iista,nri''来检查里面是否有''ed(ii)''? – steabert 2013-04-23 05:58:43

+1

是的,那也行得通。可能更简单。可以使用'if ... exit'进行'ed(ii)'测试或者让代码在'IF'块中执行。 – 2013-04-23 07:27:15

相关问题