循环

当我们需要一段代码执行很多次的时候,就需要用到循环语句

普通的do循环

Fortran中的循环使用do i=start,end[,step],其中当step为1时,可以省略

program main
   implicit none
   integer::i
   do i=1,4
      write(*,*)i
   end do
   write(*,*)"-------------------"
   do i=1,4,2      !循环中1,到4,间隔为2
      write(*,*)i  !输出奇数
   end do
   write(*,*)"-------------------"
   do i=4,1,-2      
      write(*,*)i  !反向输出偶数
   end do
end program main
$ fpm run
           1
           2
           3
           4
 -------------------
           1
           3
 -------------------
           4
           2

带条件的循环

如果要求循环在满足某些条件时执行,则需要使用do while语句

program main
   implicit none
   integer::i

   i = 1
   do while (i < 11)
      write(*,*)i
      i = i + 1
   end do
   ! 此处 i = 11
   write(*,*)"end:i=",i
end program main
$ fpm run
           1
           2
           3
           4
           5
           6
           7
           8
           9
          10
 end:i=          11

exit与cycle

遇到cycle语句,后续的语句不再执行,会自动跳到循环的开头

integer::i
do i=1,6
   if(i==5) cycle !遇到5,跳过
   write(*,*)i    !输出1,2,3,4,6
end do

遇到exit语句,后续的语句不再执行,会自动跳出循环

integer::i
do i=1,6
   if(i==5) exit !遇到5,退出
   write(*,*)i    !输出1,2,3,4
end do
  • 练习:尝试补全如上程序并运行。

无限循环

显然我们可以使用do while(.true.)构造一个无限循环,Fortran也为我们提供了如下的方式。

integer :: i

i = 1
do
  write(*,*)i
  i = i + 1
  if (i==11) exit !使用 exit 跳出
end do

命名循环

在Fortran中可以为循环命名,exitcycle语句后可以接循环的名字,这大大提高了代码的灵活性

integer::i
loop1:do i=1,10
    loop2:do j=1,10
        if(i>5)exit loop1 !满足这个条件跳出循环loop1
        write(*,*)i,j
    end do loop2
end do loop1
  • 使用循环命名可以轻松跳出多层循环

可并行化的循环(do concurrent)

Fortran2008引入,其中的代码可以自动SIMD(目前编译器实现较差,并不能保证并行执行。)

real, parameter :: pi = 3.14159265
integer, parameter :: n = 10
real :: result_sin(n)
integer :: i,j
real :: result_cos(n,n)

do concurrent (i = 1:n)  ! 注意语法和do不同使用的是: 而不是,
  result_sin(i) = sin(i * pi/4.)
end do

do concurrent (i = 1:n, j=1:n, i>j)  ! 支持i,j比较运算
  result_cos(i,j) = cos((i+j) * pi/4.)
end do
print *, result_sin
  • 支持在语句内定义循环变量do concurrent(integer::i=1:5) 目前gfortran不支持,ifx,ifort,flang支持
  • Fortran2018中引入了reduce,shared等字句,可以进一步增强该语法

隐式循环

隐式循环省略了do,end do,写起来更加方便。在数组构造器中,我们可以使用隐式循环

program main
  implicit none
  integer::i
  integer::a(4)
  a=[(i,i=1,4)]
  write(*,*)a
end program main

请读者自己尝试运行

program main
  implicit none
  integer::a(4)
  a=[(j,integer::j=1,4)] !也可以内部定义循环变量,目前`gfortran`不支持,`ifx,ifort,flang`支持
  write(*,*)a
end program main
$ fpm run --compiler="ifort"
1 2 3 4

在输出的时候也可以使用隐式循环,同时隐式循环还支持嵌套

program main
  implicit none
  integer::a(4),b(3,3)
  integer::i,j
  a=[(i,i=1,4)]
  write(*,*)(a(i),i=1,4)
  b=reshape([( [( i+3*j,i=1,3 )] ,j=1,3 )],[3,3])
  write(*,*)((b(i,j),i=1,3),j=1,3)
  write(*,*)(i,i+1,i=1,5)
end program main