演算子とフロー制御#
単純な数式と比較したコンピュータアルゴリズムの強力な利点の1つは、プログラムの_分岐_という形で現れます。これにより、プログラムは論理条件に基づいて次に実行する命令を決定できます。
プログラムフローを制御するには、主に2つの方法があります
_条件分岐_(if):ブール値(真または偽)に基づいてプログラムパスを選択します
_ループ_:コードの一部を複数回繰り返します
論理演算子#
条件分岐演算子を使用する前に、論理式を形成できる必要があります。
論理式を形成するには、以下の関係演算子セットを使用できます
演算子 |
代替 |
説明 |
---|---|---|
|
|
== 2つのオペランドが等しいかどうかをテストします |
|
|
!= / <> 2つのオペランドが等しくないかどうかをテストします |
|
|
> 左のオペランドが右のオペランドよりも厳密に大きいかどうかをテストします |
|
|
< 左のオペランドが右のオペランドよりも厳密に小さいかどうかをテストします |
|
|
>= 左のオペランドが右のオペランド以上かどうかをテストします |
|
|
<= 左のオペランドが右のオペランド以下かどうかをテストします |
以下の論理演算子も使用できます
演算子 |
説明 |
---|---|
|
左右両方のオペランドが真の場合に真 |
|
左または右、あるいは両方のオペランドが真の場合に真 |
|
右のオペランドが偽の場合に真 |
|
左のオペランドが右のオペランドと同じ論理値を持つ場合に真 |
|
左のオペランドが右のオペランドと反対の論理値を持つ場合に真 |
条件構造(if
)#
以下の例では、条件付きif
構造を使用して、angle
変数の性質を説明するメッセージを出力します
例:単一分岐if
if (angle < 90.0) then
print *, 'Angle is acute'
end if
この最初の例では、テスト式(angle < 90.0
)が真の場合に_のみ_、if
構造内のコードが実行されます。
ヒント
if
やdo
などの構造内のコードは、インデントしてコードを読みやすくすることをお勧めします。
else
キーワードを使用して、構造に代替ブランチを追加できます
例:2分岐if
-else
if (angle < 90.0) then
print *, 'Angle is acute'
else
print *, 'Angle is obtuse'
end if
これで、if
構造には2つの_ブランチ_がありますが、if
キーワードに続く論理式に応じて、_1つのブランチのみが実行されます_。
実際には、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
ループには、現在実行中のループの反復回数を追跡するために使用される整数_カウンタ_変数があります。この例では、このカウンタ変数に一般的な名前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はこのような場合に対処するための2つの実行可能文を提供しています。
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
ループをdo concurrent
に単純に置き換えるだけでは、並列実行は保証されません。上記の説明は、正しい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