2016-12-01 77 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)) 
相關問題