2016-12-01 76 views
1

是否有Fortran等价于Python的for-else语句?是否有Fortran等价于Python的for-else语句?

例如,以下内容将数字列表分类到不同的范围。在Python,它是:

absth = [1, 2, 3, 4, 5] 
vals = [.1, .2, .5, 1.2, 3.5, 3.7, 16.8, 19.8, 135.60] 


counts = [0] * len(absth) 
for v in vals: 
    for i, a in enumerate(absth): 
     if v < a: 
      counts[i] += 1 
      break 
    else: 
     counts[-1] += 1 

在Fortran中,这种工作原理相同:

do iv = 1, nvals 

    is_in_last_absth = .true. 

    do ia = 1, nabsth - 1 
    if vals(iv) < absth(ia) then 
     counts(ia) = counts(ia) + 1 
     is_in_last_absth = .false. 
     exit 
    end if 
    end do 

    if (is_in_last_absth) then 
    counts(nabsth) = counts(nabsth) + 1 
    end if 

end do 

但是,有没有办法不具有使用is_in_last_absth并且用类似Python中else更换呢?

+0

Python与NumPy和Fortran在表现力和功能方面非常相似。这罗塞塔石显示如何实施两种语言的许多常见习语并排。 http://www.fortran90.org/src/rosetta.html – jlokimlin

回答

0

据我所知,Python是唯一具有for-else语句的语言(或极少数语言之一)。不,Fortran没有它。

+0

那么,WHERE ELSEWHERE与python的“for else”有什么不同呢? – Holmz

+0

如果循环没有中断,Python的'else'会在循环之后执行*。据我所知,“别处”是在每次迭代循环中执行的。 – DyZ

1

转到语句允许任意跳转。特别是,你编写你的循环,然后是else块,然后是标记的继续。在循环中,如果条件为真,则跳转到带标签的继续。否则,for循环将正常终止,else块将被执行,然后继续,与Python的for ... else结构的语义完全匹配。

例如:

 INTEGER nabsth, nvals 
     PARAMETER (nabsth=5, nvals=9) 
     INTEGER absth(nabsth), counts(nabsth) 
     REAL vals(nvals) 
     DATA absth/1, 2, 3, 4, 5/ 
     DATA counts/0, 0, 0, 0, 0/ 
     DATA vals/.1, .2, .5, 1.2, 3.5, 3.7, 16.8, 19.8, 135.60/ 

     do iv = 1, nvals 

      do ia = 1, nabsth - 1 
      if (vals(iv) < absth(ia)) then 
       counts(ia) = counts(ia) + 1 
       goto 10 
      end if 
      end do 
      counts(nabsth) = counts(nabsth) + 1 
10  continue 
     end do 
     WRITE (*,*), counts 
     end 

可生产

 3   1   0   2   3 
+3

请不要教人们如何使用'去'陈述 –

+1

有时一个GOTO是值得的。将它们用于放置EXIT和CYCLE是有区别的。但偶尔使用并不是最大的罪恶 – Holmz

+0

如果你把你的VAX模拟器粉碎掉,你将能够在不改变任何东西的情况下运行它! – Neapolitan

2

如果问题是特别为约装箱的一系列数字,与absth正对每个区间的上限(BAR最后不具有上限),那么我可能会写这样的事情:

PROGRAM test 

    IMPLICIT NONE 

    INTEGER :: ix 
    INTEGER, DIMENSION(5) :: absth = [1, 2, 3, 4, 5] 
    REAL, DIMENSION(9) :: vals = [.1, .2, .5, 1.2, 3.5, 3.7, 16.8, 19.8, 135.60] 
    INTEGER, DIMENSION(SIZE(absth)+1) :: bins 

    bins = 0 

    DO ix = 1, SIZE(bins)-1 
    bins(ix) = COUNT(vals<absth(ix)) 
    END DO 
    bins(ix) = COUNT(vals) 

    bins = bins-EOSHIFT(bins,-1) 
    WRITE(*,*) 'bins = ', bins 
    ! which writes 3 1 0 2 0 3 

END PROGRAM test 

然后,当我很高兴逻辑是正确的时,我会把它变成一个函数并添加一些错误检查。

如果问题更笼统,并且询问什么是惯用的Fortran(后90)方法来重现Python的for-else结构,这里也有答案。

1

由于Python的for-else块的else部分仅在处理所有元素时才执行,那么如何简单地使用if语句作为最后一个元素?例如,

program main 
    implicit none 
    integer i, n 
    print *, "n = ?" ; read(*,*) n 

    do i = 1, 10 
     if (i <= n) then 
      print *, i 
     else 
      exit 
     endif 
     if (i == 10) print *, "reached the final index" 
    enddo 

    print *, "done" 
end program 

这可能对应于

n = int(input("n = ? \n")) 

for i in range(1, 11): 
    if i <= n: 
     print(i) 
    else: 
     break 
else: 
    print("reached the final index") 

print("done") 

另一种方法可能是使用标记的block结构,例如:

program main 
    implicit none 
    integer i, n 
    print *, "n = ?" ; read(*,*) n 

    loop_i : block 

     do i = 1, 10 
      if (i <= n) then 
       print *, i 
      else 
       exit loop_i 
      endif 
     enddo 
     print *, "reached the final index" 

    endblock loop_i 

    print *, "done" 
end program 

据Chap.20.1.7: “从几乎任何结构中退出”现代Fortran解释(Metcalf等人)以及F2008标准Chap.8.1.10(从here获得),可以退出blockif,associate等任何标记结构,但我们可能需要一个相对较新的编译器(gfortran-6为我工作)。 IBM手册页exit也很有用。

+0

非常感谢,我已确认文件。尽管到目前为止我从来没有使用过“并行”和“批判”,但我会在以后检查使用情况:) – roygvib

3

没有直接等价于该python构造。

请注意,通过检查循环后do变量的值,可以检测到具有计数循环控制的do循环的提前终止。

do iv = 1, nvals 
    do ia = 1, nabsth - 1 
    if (vals(iv) < absth(ia)) then 
     counts(ia) = counts(ia) + 1 
     exit 
    end if 
    end do 

    ! If the loop terminates because it completes the iteration 
    ! count (and not because the exit statement is executed) then 
    ! the do variable is one step beyond the value it had 
    ! during the last iteration. 
    if (ia == nabsth) then 
    counts(nabsth) = counts(nabsth) + 1 
    end if 
end do 

的退出声明中还可以跳出不仅仅是做循环:

do iv = 1, nvals 
    outer_block: block 
    do ia = 1, nabsth - 1 
     if (vals(iv) < absth(ia)) then 
     counts(ia) = counts(ia) + 1 
     exit outer_block 
     end if 
    end do 

    counts(nabsth) = counts(nabsth) + 1 
    end block outer_block 
end do 

和循环语句可以循环任何做构建该语句嵌套:

outer_loop: do iv = 1, nvals 
    do ia = 1, nabsth - 1 
    if (vals(iv) < absth(ia)) then 
     counts(ia) = counts(ia) + 1 
     cycle outer_loop 
    end if 
    end do 

    counts(nabsth) = counts(nabsth) + 1 
end do outer_loop 
0

有时GOTO很好。 一个可能有用的地方...

do iv = 1, nvals 

    is_in_last_absth = .true. 
    Mask = .FALSE. 
    Mask(1:(nabsth - 1)) = .TRUE.) 
    Mask2 = .FALSE. 
    WHERE(MASK) 
    WHERE(vals(iv) < absth) 
     mask2 = .TRUE. 
    ENDWHERE 

    WHERE(Mask2) 
     Count = Count + 1 
    ELSE 
     LastCount = LastCount + 1 
    ENDWHERE 

    END WHERE 
end do 

count(2:(n-1)) = count(2:(n-1))+ lastcount(1:(n)) 
相关问题