数学では 1, .., n の n × n 行列で計算するが、 この講義では他のプログラミング言語での配列と同じにするため、 0 成分から始めることにする。
2 つの添字のある配列は、2 次元配列に適用することが多い。
1 2 a00 a01 A = ( ) = ( ) 3 4 a10 a11
Ruby 言語では
#!/usr/koeki/bin/ruby
a = Array.new
a[0] = [1, 2]
a[1] = [3, 4]
と書いた。 Array.new は配列の大きさを知らせずに、変数 a に配列を代入する宣言であった。 Fortran では配列の大きさを知らせる必要がある。
program mathn
implicit none
integer i, j
real(8) a(0:1,0:1)
a(0, 0:1) = (/ 1.0d0, 2.0d0 /)
a(1, 0:1) = (/ 3.0d0, 4.0d0 /)
do i = 0, 1
write(*,*) (a(i,j), j = 0, 1)
enddo
end program mathn
Fortran での添字は数学と同様 1 から始まる。 a(2,2) で定義することも可能である。ただし添字は 1 から開始される。 Ruby や C との互換性の問題を考え、 この講義では 0 から始める。そのため型宣言のときに開始番号を明示している。 また、a(n_1,..,n_n)まである場合、n_n が、配列の次元を表す。この場合は 2 次元の配列となる。
以下、2 次元配列を行列に見立てることを考える。 Ruby 言語では、length あるいは size method を使うことにより、 代入した配列の次元を知ることができた。
#!/usr/koeki/bin/ruby
a = [1,2,3,4,5,6,7,8,9,0]
b = [a,a]
#p a.size
#p a.length
#p b.length
#p b.size
puts "a の大きさ(length) #{a.length}\t a の大きさ(size) #{a.size}"
print "b の大きさ(length) ", b.length, "\t b の大きさ(size) ", b.size, "\n"
a には 1 次元配列を、b は a から 2 次元配列を作り、それぞれの大きさを調べた。 size も length も働きは同じである。
Ruby 言語では、print や puts など、いろいろな記法で出力できる。 学部では printf("変数の説明 %d\n", var) を使用した。 ここでは、fortran と似たような記法で記してみた。 "\n" は改行文字であり、puts では行末に改行文字が入るが、 print は文末に加えておく必要があった。
Fortran には method の代わりに、組み込み関数を使って、 配列の大きさを知ることができる。 また、fortran でも実行結果の出力に説明を加えることができる。
program size
integer :: a(0:9) = (/ 1,2,3,4,5,6,7,8,9,0 /)
integer i, j
integer b(0:9,0:1)
b(0:9, 0) = a(0:9)
b(0:9, 1) = a(0:9)
!write(*,*) (b(0:9,i), i = 0,1)
!write(*,10i4) (b(0:9,i), i = 0,1)
write(*,*) 'a の大きさ shape(a) ', shape(a)
write(*,*) 'b の大きさ shape(b) ', shape(b)
end program size
2 階建ての 10 部屋のアパートが 2 次元配列 b である。配列の並びを調べて出力する部分はコメントアウトしたが、 外して出力の違いを調べておこう。前者が今までの記法による出力であるが、 隙間が大きいので、後者では出力する字数を制限する方法を取った。
write(*,'(データ数i空ける文字数)') : 整数値の場合
write(*,'(データ数e空ける文字数.小数桁数)') : 小数値の場合
数学の考え方を参照。
知っている言語で行列の転置を実行してみよう。Ruby の場合は、 mathn を使わずに表してみよう。
Ruby 言語で mathn class を使用するときは transpose method が使える。
#!/usr/koeki/bin/ruby
require 'mathn'
a = Matrix[[1,2],[3,4]]
p a.transpose
数学の考え方を参照。
4 × 4 行列を考え、 たすきがけと余韻子展開を手計算で計算をしたあと、 知っている言語で行列の逆行列を作ってみよう。 Sarrus の方法は 3 × 3 行列までは正しい結果を得ることが分かる。
答えが正しいかをすぐに知りたい場合は、Ruby 言語で mathn を使って調べることができる。
#!/usr/koeki/bin/ruby
require 'mathn'
a = Matrix[[1,2],[2,1]]
p a.determinant
p a.inverse
. をつけて配列や変数に動作を指示するものを method と呼んだ。
数値計算では単位行列の階数 (n × n のときは階数 n)をつけて、 In と表すことも多い。
ermRuby に標準でついていない 2 次元以上の配列を使用する場合は、 Fortran の方が便利な場合がある。 Ruby で require を宣言することにより、組み込み関数が使えるのと同じように、 fortran でも組み込み関数を使うことができる。
dble(a) | 倍精度型に変更 | |
matmul(m_a, m_b) | m_a, m_b は 1 次元または 2 次元配列 | |
minval(m_a(範囲:範囲,範囲:範囲)) | 最大値 | |
maxval(m_a(範囲:範囲,範囲:範囲)) | 最小値 | |
sum(m_a) | 各要素の全ての和 | |
maxloc(m_a) | 最大値はそれぞれの次元で何番目にあるか | |
minloc(m_a) | 最小値はそれぞれの次元で何番目にあるか |
Fortran にも Ruby の method と同じように、 もともと計算が可能になっている関数が定義されている。 これを組み込み関数と呼ぶ。100 × 100 の行列に、 ランダムな数字を入れ、最大と最小の値と位置を調べるプログラムで示す。
program intrin
implicit none
integer, parameter :: n = 100
real(8) s, m1, m2, b(0:n-1,0:n-1)
integer i, j, i1(0:1) ,i2(0:1)
call random_seed
call random_number(b(:,:))
s = 0.0d0
m1 = b(0,0)
m2 = m1
do j = 0, n - 1
do i = 0, n - 1
s = s + b(i, j)
if (b(i,j) < m1) then
m1 = b(i,j)
i1(0:1) = (/i, j/)
end if
if (b(i,j) > m2) then
m2 = b(i,j)
i2(0:1) = (/i, j/)
end if
end do
end do
write(*,*) m1, m2, s, i1(0:1), i2(0:1)
write(*,*) minval(b(0:n-1,0:n-1)), maxval(b(0:n-1,0:n-1)), sum(b)
write(*,*) minloc(b) -1 , maxloc(b) -1
end program intrin
表示している行で使っている組み込み関数が、計算させたものと同じ働きをすることを確かめよう。 配列のみを指定する場合と、配列の要素の範囲を指定する場合がある。
Ruby や C 言語に合わせるため、Fortran の要素のラベルを 0 から開始させていることに注意しよう。 他の言語に合わせる場合は組み込み関数でラベル部分から 1 を引く必要がある。