操作符和流程控制#
与简单的数学公式相比,计算机算法的强大优势之一是程序 分支 的形式,程序可以根据逻辑条件决定接下来要执行哪些指令。
控制程序流有两种主要形式:
Conditional (if):根据布尔值(真或假)选择程序路径
Loop:重复一段代码多次
逻辑运算符#
在我们使用条件分支运算符之前,我们需要能够形成一个逻辑表达式。
要形成逻辑表达式,可以使用以下一组关系运算符:
操作符 |
选择 |
描述 |
---|---|---|
|
|
测试两个操作数是否相等 |
|
|
测试两个操作数是否不相等 |
|
|
测试左操作数是否严格大于右操作数 |
|
|
测试左操作数是否严格小于右操作数 |
|
|
测试左操作数是否大于或等于右操作数 |
|
|
测试左操作数是否小于或等于右操作数 |
以及以下逻辑运算符:
操作符 |
描述 |
---|---|
|
如果左右操作数都为 TRUE,则为 TRUE |
|
如果左侧或右侧为 TRUE 或者两个操作数都为 TRUE,则为 TRUE |
|
如果右操作数为 FALSE,则为 TRUE |
|
如果左操作数与右操作数具有相同的逻辑值,则为 TRUE |
|
如果左操作数与右操作数具有相反的逻辑值,则为 TRUE |
条件结构(if
)#
在以下示例中,使用条件 if
结构来打印一条消息以描述 angle
变量的性质:
示例: 单分支 if
if (angle < 90.0) then
print *, 'Angle is acute'
end if
在第一个示例中,if
结构中的代码_仅在_测试表达式 (angle < 90.0
) 为真时执行。
小技巧
在 if
和 do
等结构中缩进代码是一种很好的做法,以使代码更具可读性。
我们可以使用 else
关键字向构造中添加替代分支:
示例: 两个分支 if
-else
if (angle < 90.0) then
print *, 'Angle is acute'
else
print *, 'Angle is obtuse'
end if
现在 if
结构中有两个 分支 ,但 只执行一个分支 取决于 if
关键字后面的逻辑表达式。
我们实际上可以使用 else if
添加任意数量的分支来指定更多条件:
示例: 多分支 if
-else if
-else
if (angle < 90.0) then
print *, 'Angle is acute'
else if (angle < 180.0) then
print *, 'Angle is obtuse'
else
print *, 'Angle is reflex'
end if
当使用多个条件表达式时,只有在前面的表达式都没有计算为真时,才会测试每个条件表达式。
循环结构(do
)#
在以下示例中,do
循环构造用于打印出序列中的数字。 do
循环有一个整数 counter 变量,用于跟踪当前正在执行的循环迭代。在这个例子中,我们为这个计数器变量使用了一个通用名称:i
。
当我们定义 do
循环的开始时,我们使用计数器变量名称后跟等号(=
)来指定计数变量的开始值和最终值。
示例: do
循环
integer :: i
do i = 1, 10
print *, i
end do
示例: 带有跳过的 do
循环
integer :: i
do i = 1, 10, 2
print *, i ! Print odd numbers
end do
条件循环(do while
)#
可以使用 while
关键字将条件添加到 do
循环中。循环将在 while()
中给出的条件评估为 .true.
时执行。
示例: do while()
循环
integer :: i
i = 1
do while (i < 11)
print *, i
i = i + 1
end do
! Here i = 11
循环控制语句(exit
和 cycle
)#
大多数情况下,如果满足条件,则需要停止循环。 Fortran 提供了两个可执行语句来处理这种情况。
exit
用于提前退出循环。它通常包含在 if
中。
示例: 带有 exit
的循环
integer :: i
do i = 1, 100
if (i > 10) then
exit ! Stop printing numbers
end if
print *, i
end do
! Here i = 11
另一方面,cycle
会跳过循环的剩余部分并进入下一个循环。
示例: 使用 cycle
循环
integer :: i
do i = 1, 10
if (mod(i, 2) == 0) then
cycle ! Don't print even numbers
end if
print *, i
end do
备注
在嵌套循环中使用时,cycle
和 exit
语句在最内层循环上运行。
可并行化循环(do concurrent
)#
do concurrent
循环用于显式指定循环内部没有相互依赖关系;这通知编译器它可以使用并行化/ SIMD 来加速循环的执行并更清楚地传达程序员的意图。更具体地说,这意味着任何给定的循环迭代不依赖于其它循环迭代的先前执行。任何可能发生的状态变化也必须只发生在每个 do concurrent
循环中。这些要求限制了可以放置在循环体内的内容。
简单地用
do concurrent
替换do
循环并不能保证并行执行。上面给出的解释并没有详细说明编写正确的do concurrent
循环需要满足的所有要求。编译器也可以自由地做它们认为合适的事情,这意味着它们可能不会优化循环(例如,进行简单计算的少量迭代,如下例所示)。通常,需要编译器标志来激活do concurrent
循环的可能并行化。
示例: do concurrent()
循环
real, parameter :: pi = 3.14159265
integer, parameter :: n = 10
real :: result_sin(n)
integer :: i
do concurrent (i = 1:n) ! Careful, the syntax is slightly different
result_sin(i) = sin(i * pi/4.)
end do
print *, result_sin