Fortran/変数
はじめに 編集
プログラミングにおいて変数とは、プログラムが変更できるデータの入れ物です。通常、変数を使用する前には、どのようなデータを格納するかの情報を提供するために、変数を宣言します。しかし、Fortranでは暗黙的に変数を作成することができます。 implicit
の記述がない場合、i
/I
からn
/N
まで(inグループ)で始まる宣言されていない変数や引数はinteger
となり、それ以外の宣言されていない変数や引数はreal
となります。
多くの人は、宣言せずに変数を使うことを悪習と考えています。もし変数の宣言を強制されたいのであれば、まず implicit none
をコーディングしてください。
- 簡単な例
Program Hello implicit none integer :: a1 = 10, a2 = 34 Print *, a2 end program
- 実行結果
34
行の冒頭で integer
と宣言する事で、整数の型の変数を宣言できます。
2つ以上の変数を宣言したい場合は , で区切って続けて宣言できます。
a1,a2が整数として宣言できているか確認するために、加算をしてみましょう。
- 加算
Program Hello implicit none integer :: a1 = 10, a2 = 34 Print *, a1 + a2 end program
- 実行結果
44
10+34 は 44 ですので、たしかにa1(=10)、a2(=34)ともに整数として宣言できている事が分かります。
- 型だけ宣言する場合
変数の宣言において、型だけ先に宣言しておいて後から数値を代入したい場合は、下記のようになります(下記コードの数値では、動作確認しやすくするため、数値を上記コードから変えてあります)。
- 初期化せず後から代入
Program Hello implicit none integer a1 a1 = 14 Print *, a1 end program
- 実行結果
14
このようにFortranで変数宣言をする際は、一般的に
型名 :: 変数名 = 初期値
あるいは
型名 変数名
のような構文です。
また、C++やC99以降のC言語と異なり、宣言は実行文の後には書けません。
- 実行文の後に宣言を書いたイリーガルなコード
Program Hello implicit none integer :: a1 = 42 Print *, a1 integer :: a2 = 19 Print *, a1 + a2 end program
- コンパイル結果
gfortran -ffree-form -O decl.f -o decl decl.f:5:21: 5 | integer :: a2 = 19 | 1 Error: Unexpected data declaration statement at (1) decl.f:6:19: 6 | Print *, a1 + a2 | 1 Error: Symbol 'a2' at (1) has no IMPLICIT type; did you mean 'a1'? *** Error code 1 Stop.
一般的な例 編集
通常の変数の例を以下に示します。
! Declare a constant, whose value cannot be changed.
integer, parameter :: num_days_week = 7
! Declare i as an integer, j as an array of 2 integers from j(1) to j(2), k as
! an array of 2 integers from '''k(0)''' to k(1), and m as a 2-dimensional
! array of 12 elements.
integer :: i, j(2), k(0:1), m(3,4)
! Declare c as an array of 4 floating point numbers from c(0) to c(3).
real :: c(0:3)
! Declare word as a string of length 5
character (len=5) :: word
! Declare a boolean variable with values .TRUE. or .FALSE.
logical :: tf
以下は、まったく同じことをしていますが、より短く、より古風な形になっています。
INTEGER, PARAMETER :: num_days_week = 7
DIMENSION j(2), k(0:1), m(3,4), c(0:3)
CHARACTER*5 word
LOGICAL tf
メモリのレイアウトを重視する場合は、m(1,1)の後にm(2,1)が続き、m(1,2)は続かないことに注意してください。
変数に値を設定するには、変数を等号の前に置き、等号の後に設定される値を置く。上記の宣言を行うと、以下のような代入が可能です。
i = 3*4 ! Set i to 3*4 = 12
j = [1, 4] ! Set j(1) to 1, j(2) to 4
c = [1.0, 4.0, 5.0, 9.0] ! Set c(0) to 1.0, c(1) to 4.0, c(2) to 5.0, c(3) to 9.0
word = 'dog' ! Set word = "dog " . The variable word is padded with spaces on the right
tf = .true. ! Set tf to True
変数は、代入の両サイドに現れることができます。右辺が先に評価され、その値に変数が代入されます。
i = 3 ! i has value 3
i = i**i ! i has value 3**3 = 27
変数はある型から別の型に変換することができますが、C++やJavaのように変数を型付けするのではなく、Fortranでは固有の手続きを使用します。
real :: r = 1.5
real (kind=8) :: d = 1.5
integer :: i = 1
print *, dble(r), dble(d), dble(i) ! Convert number to a double precision
print *, real(r), real(d), real(i) ! Convert number to a single precision (REAL)
print *, int(r), int(d), int(i) ! Convert number to an integer
また、同じことをよりシンプルで古風な形で表現しています。
DOUBLE PRECISION d = 1.5
r = 1.5
i = 1
PRINT *, DBLE(r), DBLE(d), DBLE(i)
PRINT *, REAL(r), REAL(d), REAL(i)
PRINT *, INT(r), INT(d), INT(i)
配列 編集
宣言 編集
配列の宣言には2種類の表記法があります。次の例は、integer
型で長さ5の配列の表記法を示しています。
integer, dimension (5) :: arr1
integer :: arr2(5)
多次元配列の場合は、各次元の長さを指定する必要があります。次の例では、5x6の整数行列が長さ(5,6)の2次元配列になっている場合を示しています(ここでも両方の表記をしています)。
integer, dimension (5,6) :: arr1
integer :: arr2(5,6)
初期化 編集
配列を実際の値で初期化するには、特定の要素,特定の範囲,あるいは配列全体を設定するという複数の選択肢があります。
integer :: arr(3)
arr(1) = 4 ! set specific element
arr(1:2) = [4, 5] ! set a range aka slicing notation
arr = [4, 5, 6] ! set whole array
- 様々な配列変数の初期化方法
Program Init integer::a (5) = [1, 2, 3, 4, 5] ! 配列構成子の代替形式 integer::b (5) = (/1, 2, 3, 4, 5/) ! 配列構成子スカラ式 integer::c (5) = (/(i, i=1, 5)/) ! 配列構成子DO形反復 integer::x (5) = 1 ! 配列要素を全て1に Print *, a Print *, b Print *, c Print *, x x = a ! 配列変数に配列変数を代入 Print *, x Print *, x * 2 ! 配列変数xの要素全てに _ * 2 Print *, 2 ** x ! 配列変数xの要素全てに 2 ** _ end program
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 1 1 1 1 1 2 3 4 5 2 4 6 8 10 2 4 8 16 32
多次元配列を設定するには、reshape
やshape
コマンドを利用する必要があります。
integer :: arr(2,3)
arr = reshape([1,2,3,4,5,6], shape(arr))
! arr = reshape([1,2,3,4,5,6], shape=[2,1]) ! same effect as above command - hardcode the shape of arr
! arr represents matrix:
! 1 3 5
! 2 4 6
Fortranでは列メジャーな順序を採用しているため、上の例ではよくわからない行列ができてしまいます。行メジャーの順序では,次の例のように,どの次元で最初にソートするかを order 引数で指定することができます.
integer :: arr(2,3)
arr = reshape([1,2,3,4,5,6], shape(arr), order=[2,1])
! arr represents matrix:
! 1 2 3
! 4 5 6