【Fortran学習|豆知識】配列の最大・最小要素の位置を瞬時に取得!MAXLOC/MINLOC関数活用術

はじめに:なぜMAXLOC/MINLOC関数が重要なのか?

数値計算やデータ分析において、配列の中から最大値や最小値を持つ要素を見つけ出すことは非常に頻繁に行われます。しかし、単に最大値・最小値そのものを取得するだけでなく、その「位置」(インデックス)を知りたい場面も少なくありません。例えば、構造解析で最大応力が発生した点の座標を特定したい、画像処理で最も明るいピクセルを見つけたい、といったケースです。

従来の方法では、配列をループで走査して最大値・最小値とそのインデックスを逐一記録していく必要があり、コードが冗長になりがちでした。MAXLOC関数とMINLOC関数は、このような課題を解決し、配列の最大値・最小値を持つ要素のインデックスを効率的かつ簡潔に取得できる強力なツールなのです。

MAXLOC/MINLOC関数とは?基礎知識を徹底解説

MAXLOC関数とMINLOC関数は、配列内の最大値または最小値を持つ要素の「インデックス」を配列として返します。これは、単に最大値や最小値そのものを返す `MAXVAL` 関数や `MINVAL` 関数とは異なる点です。

  • インデックス (Index): 配列の各要素を一意に識別するための番号です。一次元配列では `1`, `2`, `3`… といった整数、二次元配列では `(行番号, 列番号)` のようにタプル形式で表されます。
  • 配列演算 (Array Operation): 配列全体に対して、要素ごとに一括して計算を実行する機能です。これにより、ループ処理を記述せずに簡潔なコードで効率的な計算が可能になります。MAXLOC/MINLOC関数もこの配列演算の一種と言えます。
  • スライシング (Slicing): 配列の一部を取り出す機能です。MAXLOC/MINLOC関数は、配列全体または指定した範囲(スライス)に対して適用できます。

MAXLOC関数は最大値のインデックスを、MINLOC関数は最小値のインデックスを返します。もし最大値または最小値が複数存在する場合、これらの関数は最初に見つかった要素のインデックスを返します。

MAXLOC/MINLOC関数の使い方:実践的なコード例

ここでは、二次元配列を例に、MAXLOC関数とMINLOC関数の使い方を見ていきましょう。

まず、サンプルとなる二次元配列を定義します。

program maxloc_minloc_example
implicit none

! 二次元配列の定義
real :: temperature(3, 4) = reshape( (/ &
35.5, 36.2, 37.1, 38.0, &
34.9, 35.8, 36.5, 37.2, &
33.1, 34.2, 35.0, 36.0 &
/), shape(temperature) )

! 結果を格納する変数
integer :: max_pos(size(temperature, dim=1)) ! 最大値のインデックスを格納
integer :: min_pos(size(temperature, dim=1)) ! 最小値のインデックスを格納

! — 最大値のインデックスを取得 —
! temperature配列全体から最大値を持つ要素のインデックスを取得します。
! 例: temperature(i, j) の i と j が返されます。
max_pos = maxloc(temperature)

! — 最小値のインデックスを取得 —
! temperature配列全体から最小値を持つ要素のインデックスを取得します。
! 例: temperature(i, j) の i と j が返されます。
min_pos = minloc(temperature)

! — 結果の表示 —
print , “— 温度データ —”
call print_array(temperature)
print
print , “最大値を持つ要素のインデックス: “, max_pos
print , “最小値を持つ要素のインデックス: “, min_pos
print , “最大値: “, temperature(max_pos(1), max_pos(2)) ! 取得したインデックスを使って最大値にアクセス
print , “最小値: “, temperature(min_pos(1), min_pos(2)) ! 取得したインデックスを使って最小値にアクセス

contains

! 配列を整形して表示するサブルーチン
subroutine print_array(arr)
implicit none
real, dimension(:,:), intent(in) :: arr
integer :: i, j

do i = 1, size(arr, dim=1)
do j = 1, size(arr, dim=2)
write(, ‘(F6.1)’) arr(i, j)
end do
print
end do
end subroutine print_array

end program maxloc_minloc_example

このコードでは、`temperature` という3行4列の二次元配列を定義し、`maxloc` 関数と `minloc` 関数を使って最大値と最小値のインデックスを取得しています。`max_pos` と `min_pos` は、返されるインデックスを格納するための変数です。二次元配列の場合、`maxloc` や `minloc` は `(行番号, 列番号)` の形式でインデックスを返しますが、Fortranの配列変数に格納する際には、多次元配列を一次元配列のように扱うための工夫が必要になる場合があります。上記の例では、`max_pos` と `min_pos` を配列として宣言し、返されたインデックスを格納しています。

実行結果は以下のようになります(環境によって多少異なる場合があります)。

— 温度データ —
35.5 36.2 37.1 38.0
34.9 35.8 36.5 37.2
33.1 34.2 35.0 36.0

最大値を持つ要素のインデックス: 1 4
最小値を持つ要素のインデックス: 3 1
最大値: 38.00000
最小値: 33.10000

この結果から、最大値 `38.0` はインデックス `(1, 4)`、最小値 `33.1` はインデックス `(3, 1)` に存在することがわかります。

応用と注意点:現場で役立つヒント

  • 複数要素の処理: もし最大値や最小値が複数箇所に存在し、それら全てを処理したい場合は、`MAXLOC` や `MINLOC` 関数だけでは直接対応できません。この場合は、`MAXVAL` や `MINVAL` で最大値・最小値を取得した後、条件分岐(`WHERE`文など)と組み合わせて該当するインデックスを特定する必要があります。
  • 次元の指定: `MAXLOC` や `MINLOC` 関数は、特定の次元に沿って最大値・最小値のインデックスを求めることも可能です。例えば、`maxloc(temperature, dim=1)` とすると、各列の最大値のインデックス(行番号)が返されます。
  • データ型: MAXLOC/MINLOC関数は、整数型、実数型、複素数型、論理型など、様々なデータ型の配列に適用できます。
  • パフォーマンス: ループを自作するよりも一般的に高速ですが、非常に大規模な配列や特殊な状況では、パフォーマンスチューニングが必要になる場合もあります。

MAXLOC/MINLOC関数を使いこなすことで、コードの可読性と効率性を大幅に向上させることができます。ぜひ、日々のコーディングで活用してみてください。

コメント

タイトルとURLをコピーしました