匿名希望のおでんFortranツヴァイさん太郎

生き物、Fortran、川について書く

論理型(logical)変数の使い方

Fortranでは変数の型として

  • 整数型 integer
  • 実数型 real
  • 倍精度実数型 double precision
  • 複素数型 complex
  • 倍精度複素数型 complex(kind(0d0))
  • 論理型 logical
  • 文字型 character

が使えます.今日の話題は論理型(logical)変数です.

長い間これはどんな場合に使う変数なのか理解できませんでした.簡単な計算ばかりしているときにはありがたみが全く分からなかったのです.1と0で代用できるような場面ばかりだとまず使うことがありませんでした.

データの加工などをするときにはpack関数などのmaskを伴う配列関数をよく使います.このmaskの指定に論理型が使えます.統計処理をするようになってからこの手の関数を使うことが多くなり,やっと論理型変数のありがたみが分かりました.

かんたんな例を挙げましょう.細かい説明はコメントアウトを読んでください.

program main
implicit none

!    Loop
integer i
!    Parameter
integer, parameter::n = 10
integer, parameter::x(n) = (/(i, i=1, n)/)
integer, parameter::y(n) = (/1, 200, 3, 400, 5, 600, 7, 800, 9, 1000/)
logical masking(n)


!    論理型の値は.true.または.false.
!    true, falseの前後のピリオドを忘れないように
masking(:) = .true.
print*, masking(:)
masking(:) = .false.
print*, masking(:)
print*, 


!    pack関数はこのように使う
!    材料となる配列xの成分の内,mask=で指定した条件がtrueの部分に
!    相当する成分だけをまとめた配列を作る
!    従って,maskの条件はxに関する条件でなくてもよい(以下の配列yによるmaskがその例)
print'(A31, 5(" "), 10i3)', "pack(x, mask=mod(x(:), 2) == 1)", pack(x, mask=mod(x(:), 2) == 1)
print'(A31, 5(" "), 10i3)', "pack(x, mask=y(:) < 10)", pack(x, mask=y(:) < 10)

!    pack関数のmask=は省略可能
print'(A31, 5(" "), 10i3)', "pack(x, mod(x(:), 2) == 1)", pack(x, mod(x(:), 2)==1)
print'(A31, 5(" "), 10i3)', "pack(x, y(:) < 10)", pack(x, mask=y(:) < 10)
print*, 


!    maskやif文などで書く論理式は.true.または.false.を返すので,実はprint文でこのように出力できる
!    なお,以下では配列であることを明示的にするためx(:)と書いている
!    それぞれ,mod(x, 2) == 1,x < 5,x >= 5と書いてもよい
print'(A17, 5(" "), 10L3)', "mod(x(:), 2) == 1", mod(x(:), 2) == 1
print'(A17, 5(" "), 10L3)', "x(:) < 5", x(:) < 5
print'(A17, 5(" "), 10L3)', "x(:) >= 5", x(:) >= 5
print*, 


!    pack関数はmask=の値が.true.の部分の要素を集めるので,論理型配列で指定可能
masking(:) = mod(x, 2) == 1
print'(A21, 5(" "), 10i3)', "x(:)", x(:)
print'(A21, 5(" "), 10L3)', "masking(:)", masking(:)
print'(A21, 5(" "), 10i3)', "pack(x, mask=masking)", pack(x, mask=masking)
print*, 

masking(:) = y(:) < 10
print'(A21, 5(" "), 10i3)', "x(:)", x(:)
print'(A21, 5(" "), 10L3)', "masking(:)", masking(:)
print'(A21, 5(" "), 10i3)', "pack(x, mask=masking)", pack(x, mask=masking)

end program


出力結果

 T T T T T T T T T T
 F F F F F F F F F F

pack(x, mask=mod(x(:), 2) == 1)       1  3  5  7  9
        pack(x, mask=y(:) < 10)       1  3  5  7  9
     pack(x, mod(x(:), 2) == 1)       1  3  5  7  9
             pack(x, y(:) < 10)       1  3  5  7  9

mod(x(:), 2) == 1       T  F  T  F  T  F  T  F  T  F
         x(:) < 5       T  T  T  T  F  F  F  F  F  F
        x(:) >= 5       F  F  F  F  T  T  T  T  T  T

                 x(:)       1  2  3  4  5  6  7  8  9 10
           masking(:)       T  F  T  F  T  F  T  F  T  F
pack(x, mask=masking)       1  3  5  7  9

                 x(:)       1  2  3  4  5  6  7  8  9 10
           masking(:)       T  F  T  F  T  F  T  F  T  F
pack(x, mask=masking)       1  3  5  7  9


以上の例のように,trueかfalseをもとにmaskするというのが重要であり,便利なところです.条件によってmaskの内容が異なる場合には,このような論理型変数が威力を発揮します.


(2018.07.13追記
論理型変数を利用して関数を作った例はこちら.
y-tis.hatenablog.com

(2018.08.11追記
pack関数を使うときにも同様の考え方をします.
y-tis.hatenablog.com