基本とプログラム構造
プログラム構造とHello World
すべてのFortranプログラムは'program NAME'で始まり、'end program NAME'で終わる。'implicit none'はモダンFortranで必須 — すべての変数の明示的な宣言を強制(これがないと、Fortranはi-nで始まる変数を整数、それ以外を実数とする暗黙の型付けを使用し、これはバグの大きな原因)。'contains'ブロックが実行可能コードを内部プロシージャ(プログラム内で定義されたサブルーチン/関数)から分離。コメントは'!'で始まる。自由ソース形式(Fortran 90+)は.f90拡張子を使用、列は関係ない。gfortran/ifortでコンパイル。
program hello
! A complete Fortran program structure
implicit none
! declarations go here
integer :: status = 0
print *, "Hello, World!" ! list-directed output to stdout
! executable statements
call do_work(status)
print *, "Exit status: ", status
contains
subroutine do_work(st)
integer, intent(out) :: st
st = 0
print *, "Working..."
end subroutine do_work
end program hello
! Compile: gfortran hello.f90 -o hello
! Run: ./hello変数と組み込み型
Fortranには5つの組み込み型:integer、real、complex、character、logicalがある。'kind'が精度/サイズを選択 — 64ビットにはkind=8を使用(または移植性のためselected_real_kind/iso_fortran_envを使用)。実 数リテラルにはkind接尾辞が必要:3.14_8(3.14だけではなく)。double precisionはreal(kind=8)のレガシー構文。複素数リテラルは(real, imag)形式。論理値は.true. / .false.(ドット付き)。文字列はlen=:とallocatableで宣言しない限り固定'len'を持つ(遅延長、Fortran 2003+)。暗黙の精度損失を避けるため常に一致するkind接尾辞で初期化。
program variables
implicit none
! Integer types
integer :: count = 0
integer(kind=8) :: big = 9223372036854775807_8 ! 64-bit
! Real types
real :: x = 3.14 ! default (often 32-bit)
real(kind=8) :: y = 2.718281828459045_8 ! double precision
double precision :: z = 1.0d0
! Complex
complex :: c = (1.0, 2.0) ! 1 + 2i
complex(kind=8) :: cw = (1.0_8, 2.0_8)
! Character
character(len=20) :: name = "Alice"
character(len=:), allocatable :: flexible ! deferred length
! Logical
logical :: flag = .true.
! Print all
print *, count, big
print *, x, y, z
print *, c, cw
print *, name, flag
end program variables定数とパラメータ
定数は'parameter'属性を使用し、宣言時に初期化必須。変更不可 — コンパイラが最適化とインライン化可能。慣習でSCREAMING_SNAKE_CASEを使用。character(*)は'初期化子から長さを取る'を意味(文字列定数に便利)。パラメータは配列サイズ、物理定数、列挙風整数コードに一般的に使用。Fortran 2003+には適切なENUM型もあるがパラメータ整数が慣用的な選択。パラメータは配列次元宣言や他の定数式コンテキストで使用可能。
program constants
implicit none
! Named constants via 'parameter' attribute
integer, parameter :: MAX_SIZE = 100
real, parameter :: PI = 3.14159265
real, parameter :: E = 2.718281828
character(*), parameter :: APP_NAME = "MyApp"
! Using parameters
real :: arr(MAX_SIZE)
arr = 0.0
print *, APP_NAME, " size=", MAX_SIZE
print *, "Circumference: ", 2.0 * PI * 5.0
! Enum-like via parameter
integer, parameter :: SUNDAY = 1, MONDAY = 2, TUESDAY = 3
integer :: day = MONDAY
print *, "Day code: ", day
end program constants演算子と式
Fortran演算子:算術(+ - * / **)、**はべき乗(Fortranに固有)。整数除算はゼロ方向に切り捨 て — 真の除算にはreal(a)/bを使用。2つの関係構文:モダン(< > == /= <= >=)とレガシー(.lt. .gt. .eq. .ne. .le. .ge.)。論理:.and. .or. .not. .eqv.(同値).neqv.(排他的論理和)。文字列連結は//を使用、trim()が後続スペースを削除(Fortranは固定長文字列をスペースでパディング)。mod vs modulo:modは切り捨て除算の符号に従い、moduloは床除算に従う — 負のオペランドで異なる。
program operators
implicit none
integer :: a = 17, b = 5
real :: x = 2.0
! Arithmetic
print *, a + b, a - b, a * b ! 22 12 85
print *, a / b ! 3 (integer division!)
print *, real(a) / b ! 3.4 (cast to real)
print *, a ** 2 ! 289 (exponentiation)
print *, mod(a, b) ! 2 (modulo)
print *, modulo(a, b) ! 2 (differs for negatives)
! Relational (both forms work)
print *, a > b, a < b ! T F
print *, a .gt. b, a .lt. b ! T F (old form)
print *, a == b, a /= b ! F T
! Logical
print *, (a > 0) .and. (b > 0) ! T
print *, (a > 0) .or. (b < 0) ! T
print *, .not. (a > 0) ! F
print *, (a > 0) .eqv. (b > 0) ! T (equivalence)
! String concatenation
character(10) :: s1 = "Hello", s2 = "World"
print *, trim(s1) // " " // trim(s2) ! Hello World
end program operators組み込み関数と数学
Fortranには豊富な組み込み(ビルトイン)関数がある。数学:abs、sqrt、exp、log(自然)、log10、sin/cos/tan/asin/acos/atan/atan2、sinh/cosh/tanh。丸め:int(切り捨て)、nint(最近接)、floor、ceiling。変換:real()、int()、cmplx()。問い合わせ:size、shape、huge(最大値)、tiny(最小正値)、kind。すべての三角関数はラジアンを取る。atan2(y, x)は正しい象限の角度を返す(atanと異なる)。範囲制限のチェックにhuge/tinyを使用。組み込み関数は要素的 — 配列上で自動的に要素ごとに動作。
program intrinsics
implicit none
real :: x = -3.7, y = 2.5
! Math functions
print *, abs(x) ! 3.7
print *, sqrt(2.0) ! 1.414...
print *, exp(1.0) ! 2.718... (e^x)
print *, log(2.0) ! 0.693... (natural log)
print *, log10(1000.0) ! 3.0
print *, sin(3.14159/2) ! 1.0
print *, cos(0.0) ! 1.0
print *, atan2(1.0,1.0) ! 0.785... (pi/4)
! Rounding
print *, int(x) ! -3 (truncate toward zero)
print *, nint(x) ! -4 (nearest integer)
print *, floor(x) ! -4 (toward -inf)
print *, ceiling(x) ! -3 (toward +inf)
print *, abs(x), max(x, y), min(x, y) ! 3.7 2.5 -3.7
! Type conversion
print *, real(5) ! 5.0
print *, int(3.9) ! 3
! Inquiry
real :: arr(10)
print *, size(arr) ! 10
print *, huge(1) ! 2147483647
print *, tiny(1.0) ! smallest positive real
end program intrinsics制御フロー
If...Then...Else
ブロックIF:'if (cond) then ... else if (cond) then ... else ... end if'。各分岐には'then'が必要(最後のelseを除く)。論理IFは1行:'if (cond) statement'('then'/'end if'なし)。条件は関係演算子(< > == /= <= >=または.lt. .gt. .eq. .ne. .le. .ge.)と.and. .or. .not.の組み合わせ。'stop'がプログラムを終了(オプションでメッセージ/コード付き)。算術IF(if (x) label1, label2, label3)はFortran 2018で削除 — 絶対に使用しない。宣言されていない変数をキャッチするため常に'implicit none'を使用。
program if_demo
implicit none
integer :: score = 85
character(1) :: grade
! Multi-branch if/else if/else
if (score >= 90) then
grade = 'A'
else if (score >= 80) then
grade = 'B'
else if (score >= 70) then
grade = 'C'
else if (score >= 60) then
grade = 'D'
else
grade = 'F'
end if
print *, "Score ", score, " -> Grade ", grade
! Logical if (single statement, no 'then')
if (score < 0 .or. score > 100) stop "Invalid score"
! Arithmetic if (OBSOLETE - avoid)
! if (x) 10, 20, 30 ! jump to label based on sign
end program if_demoSelect Case(Switch)
select caseはFortranのswitch文。ケースは単一値(case (3))、リスト(case (1, 3, 5))、または範囲(case (4:5)は4から5を含む)。case defaultがフォールバック。Cと異なり、フォールスルーなし — 各分岐は独立で1つのみ実行。整数、文字、論理型で動作(実数は不可)。文字範囲はASCII順序('A':'Z')。浮動小数点比較にはif/elseを使用。select caseは整数/文字ディスパッチに長いif/else ifチェーンより効率的(コンパイラがジャンプテーブルを使用可能)。
program case_demo
implicit none
integer :: day = 3
character(1) :: ch = 'A'
character(10) :: day_name
! Integer select case
select case (day)
case (1)
day_name = "Monday"
case (2)
day_name = "Tuesday"
case (3)
day_name = "Wednesday"
case (4:5)
day_name = "Thu/Fri"
case (6:7)
day_name = "Weekend"
case default
day_name = "Invalid"
end select
print *, day_name
! Character select case (case-insensitive via pre-upper)
select case (ch)
case ('A':'Z')
print *, "Uppercase letter"
case ('a':'z')
print *, "Lowercase letter"
case ('0':'9')
print *, "Digit"
case default
print *, "Other"
end select
! Logical select case
select case (day > 5)
case (.true.)
print *, "Weekend!"
case (.false.)
print *, "Weekday"
end select
end program case_demoDoループ(カウント)
カウントDOループ:'do var = start, end, step'(stepはデフォルト1)。ループはvar <= end(正のstep)またはvar >= end(負のstep)の間実行。varは各反復後にインクリメント。暗黙do構文[(expr, var=start,end)]は配列初期化とI/Oリストに強力。名前付きループ(outer: do ... end do outer)はcycle/exitを特定のネストレベルにターゲット可能。ループ変数は自動的に定義、Fortranではループ後に最終値を保持。ループ本体内でループ変数を変更しない。
program do_loops
implicit none
integer :: i, j, total
! Basic counted loop: do var = start, end [, step]
do i = 1, 5
print *, i ! 1 2 3 4 5
end do
! With step
do i = 10, 1, -1 ! countdown
print *, i
end do
do i = 0, 100, 25 ! 0 25 50 75 100
print *, i
end do
! Implied-do (inline, for array init / I/O)
integer :: arr(5) = [(i**2, i=1,5)] ! 1 4 9 16 25
print *, arr
print *, (i, i=1,3) ! 1 2 3
! Nested loops with labels (for cycle/exit targeting)
total = 0
outer: do i = 1, 3
inner: do j = 1, 3
total = total + i*j
end do inner
end do outer
print *, "Total: ", total
end program do_loopsDo Whileと無限ループ
do while (cond) ... end doは事前テストループ(各反復前に条件チェック、ゼロ回実行の可能性あり)。事後テストビヘイビアにはdo ... if (cond) exit ... end doを使用。裸の'do ... end do'は無限ループ — exit文が必須(そうでなければ無限)。'exit'は最内ループ(または名前付きループ)を脱出。名前付きループ(factorial_loop:)でexitが外側ループをターゲット可能。反復回数が未知で条件に依存する場合はdo whileを、回数が事前に分かっている場合はカウントdoを使用。
program while_demo
implicit none
integer :: n, count
real :: x, sum
! do while: pre-test loop
n = 1024
count = 0
do while (n > 1)
n = n / 2
count = count + 1
end do
print *, "log2(1024) = ", count ! 10
! Infinite loop with exit
sum = 0.0
do
read(*, *) x
if (x < 0) exit ! leave loop
sum = sum + x
end do
print *, "Sum: ", sum
! do ... end do with conditional exit
n = 1
factorial_loop: do
if (n > 10) exit factorial_loop
print *, n, factorial(n)
n = n + 1
end do factorial_loop
contains
recursive function factorial(n) result(f)
integer, intent(in) :: n
integer :: f
if (n <= 1) then
f = 1
else
f = n * factorial(n-1)
end if
end function factorial
end program while_demoCycle、Exitとループ制御
cycleは現在の反復の残りをスキップし次へジャンプ(C/Pythonの'continue'のようなもの)。exitはループから完全に脱出('break'のようなもの)。デフォルトで最内ループをターゲットするが、名前付きループ(search: do ... end do search)で外側ループをターゲット可能:'exit search'または'cycle search'。これはネストしたループをクリーンに脱出するのに不可欠。フィルタリング(不要な反復をスキップ)にcycle、早期終了(検索発見、エラー検出)にexitを使用。名前付きループでネストした制御フローを明示的で読みやすく。