循环
当我们需要一段代码执行很多次的时候,就需要用到循环语句
普通的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中可以为循环命名,exit
和cycle
语句后可以接循环的名字,这大大提高了代码的灵活性
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