2.1 ベクトルと行列を作る
2.1.1 ベクトルを作る:[. . .]
ベクトル(vector)とは, 数あるいは文字といった同じ種類の 成分(element)あるいは要素を, 縦一列あるいは横一列に並べたものです. 構成要素を横一列に並べたベクトルを 行ベクトル(row vector),縦一列に並べたベクトルを 列ベクトル(column vector)と呼びます.
高校数学では,ベクトルはアルファベットの小文字の上に矢印をつけて,
のように表します.大学数学では,アルファベットの小文字を太字にして,
のように表します.
MATLAB で行ベクトルを作成するには,半角スペースを空けて要素を書き並べ, [ ] で囲みます(例題 ex2101a). 半角スペースのかわりにコンマ(,)で要素を区切ってもいいです(例題 ex2101b).
MATLAB で列ベクトルを作成するには要素をセミコロン(;)で区切ります(例題 ex2011c). あるいは,2.3.4 節で学習する,行列を 転置(transpose)する演算子「 '」を用いて, 行ベクトルを列ベクトルにします(例題 ex2101d). 例題 ex2101d は
X = [1 2 3 4 5];
X = X'
と書くこともできます.
テキストではアルファベットの大文字で表される変数にベクトルを保存していますが, 数学ではアルファベットの小文字でベクトルを表すことが多いので, ベクトルを保存する変数は小文字にしてもよいと思います.
2.1.2 等差数列をなす成分を持つベクトル::
等差数列(arithmetic sequence)は等間隔の数の並びです.間隔を 公差(common difference)と呼びます. たとえば,最初の数である 初項(the first term)が 1 で,公差が 1 の数列は 1, 2, 3, 4, ... となります.初項が 2 で公差が 3 の数列は 2, 5, 8, 11, ... となります.
初項を , 公差を とすると,第2項 は です.第3項 は となります.
テキストの式 (2.1) で第 項 と第 項には誤植があります(改訂版第1刷). 正しくは,
および
です.
要素が等差数列をなす行ベクトルは,要素をすべて書き並べなくても,
初項:公差:末項
という式で作ることができます(例題 ex2102a). この式では,ベクトルの要素を囲む [ ] は不要です([ ] をつけてもエラーにはなりません).
公差を負の数にすると, 要素である数が等間隔で減少していくベクトルとなります(例題 ex2102b). 公差が 1 のときは省略できます(例題 ex2102c).
1.3.4 節で一度説明したように,式 a:d:b での b は, 初項 a に公差 d を順に加えていってできる数になっていなくてもかまいません. この場合,数列において b を超えない最後の数が末項となります. たとえば,
0:0.11:1
という式を試してください.末項は 0.9900 となります.
要素が等差数列をなす列ベクトルを作りたければ, 行ベクトルを作成する式を ( ) で囲み,転置します. たとえば,例題 ex2102a のベクトルを列ベクトルとして作りたければ,
X = (1:0.25:2)'
とします.
2.1.3 行列を書く:;
行列(matrix)とは, 数あるいは文字といった同じ種類の 成分(element)あるいは要素を, 縦横に並べたものです.
数学では,行列はアルファベットの大文字で
のように表します.
行列において,横方向の要素の並びを「行」(row), 縦方向の要素の並びを「列」(column)と呼びます. 上の行列は3行3列の行列です. 1行目は [1 2 3],2行目は [4 5 6],3行目は [7 8 9] です. 行ベクトルは1行だけの行列,列ベクトルは1列だけの行列と考えることができます.
行列の成分を文字で表すときには,その行列を表すアルファベットの小文字を用いて,
と書きます.添え字は行と列を表しており, を 成分と呼びます.
MATLAB で行列を作るには,以下のように, 行ベクトルを作る途中で改行を指示します. 改行の指示はセミコロン(;)です.
A = [1 2 3; 4 5 6; 7 8 9]
あるいは,例題 ex2103b のように, セミコロンで区切るかわりに改行してもいいです.
以上の方法で行列を作るとき,各行の要素数は同じでなければなりません. 要素数がそろっていないとエラーとなります.
2.1.4 ベクトルから行列を作る
行ベクトルを縦に並べるか,列ベクトルを横に並べると,行列を作ることができます. 並べるベクトルの要素数は同じでなければなりません. 例題 ex2104 では,2つの行ベクトル(要素数は4)X および Y を縦に並べて, 2行4列の行列 A を作っています.
練習問題をひとつ出しておきます.
ex2104 で X = 1:4; Y = 2:5 という2つの行ベクトルを作成しました. これら2つのベクトルを用いて,行列 を作成してください.Bを直接に B = [1 2; 2 3; 3 4; 4 5] と書くのではなく,X と Y から作成してください.
解答は2通りあると思います.
2.2 有用な行列を作る
2.2.1 零行列:zeros
すべての要素が 0 の行列を 零行列(zero matrix, null matrix)と呼びます. MATLAB では zeros 関数で零行列を作ることができます.
零行列の用途のひとつはデータの保存です. データを保存する行列としてあらかじめ作成しておき, データが得られたら行列の中の特定の場所に保存します. エクセルの新規ワークシートのような空白の行列は作成できないので, すべての要素が 0 の行列を作成します.
正方行列(square matrix)とは行数と列数が等しい行列です. 正方行列における行あるいは列の要素数を,正方行列の 次数(order)と呼びます.
2.2.2 1 行列:ones
すべての要素が 1 の行列を 1 行列(matrix of ones, all-ones matrix)と呼びます. MATLAB では ones 関数で零行列を作ることができます.
第1章の例題 ex1403b で 1 行 100 列の 1 行列(つまり, 100 個の 1 を並べた行ベクトル)を作りました.
2.2.3 単位行列:eye
単位行列(unit matrix, identity matrix)は, 左上から右下の対角線に 1 が並び,他の要素はすべて 0 の正方行列です.
単位行列は記号 あるいは で表します. MATLAB で単位行列を作成する eye 関数はこの記号 に由来します(発音が同じ).
単位行列は行列の乗算での「1」です. すなわち,行列 と単位行列をかけると, もとの のままで変化しません. 行列 と単位行列 を
A = [1 2 3; 4 5 6; 7 8 9]
I = eye(3)
として,行列の乗算
A * I
I * A
の結果がいずれも となることを観察してください.
行列の乗算の規則については 2.3.2 節で説明します.
行列の乗算は,実数と異なり,ある条件が満たされないと実行できません. 単位行列と乗算ができる正方行列は,単位行列と次数が同じものに限られます. 行列の乗算は,やはり実数と異なり, と の結果は一般に一致しません(交換法則が成立しない). しかし,正方行列は次数が同じ単位行列の左からも右からも乗算ができて, となります.
正方行列でない(行数と列数が異なる)行列では,
- 単位行列の左からかける場合は,その単位行列と列数が同じであること.
- 単位行列の左からかける場合は,その単位行列と行数が同じであること.
という条件を満たせば単位行列との乗算が可能で, 結果はもとのままです. 行列 および と, 単位行列 を
A = [1 2 3; 4 5 6]
B = [1 2; 3 4; 5 6]
I = eye(3)
として,
A * I
I * A
B * I
I * B
の結果を観察してください.このうち2つはエラーとなります.
2.2.4 対角行列:diag
正方行列において,左上から右下の対角線上に並んでいる成分を 対角成分(diagonal elements)と呼びます.
対角行列(diagonal matrix)は, 対角要素「以外」が 0 の行列です. MATLAB では diag 関数で対角行列を作ることができます.
対角行列「もどき」を作成する例題 ex2204b の結果は少し戸惑うかもしれません. いずれの場合も正方行列ができるということに注意してください. たとえば,
X = 1:3
A = diag(X, 1)
を考えてみます.もし
A = diag(X)
とすれば,対角成分が 1, 2, 3 である3次の正方行列が作られます. この対角成分を対角線のひとつ上側にずらすには
A = diag(X, 1)
とします.これを行うためには第4列を追加する必要がありますね(そうしないと, 3 を入れる場所がない). そうすると,正方行列であることを保つためには,第4行もあわせて追加することになります.
2.2.5 乱数を成分とする行列:rand, randn
一様分布(uniform distribution)とは.直観的には, 特定区間の実数が等確率で出現するデータの発生装置です. たとえば,ルーレットを回して,最初の針の位置から針が止まった位置までの角度を測定すれば, 0 度から 360 度までの実数がひとつ得られます. この区間の値は等確率で得られるはずです.
統計学を学習した人のために説明を捕捉しておきます. 連続分布での個々の値の出現確率は 0 なので, 上述の説明はおかしいと思うかもしれません. ここでは直観的な理解を優先しています. それに,MATLAB が返す乱数の値は桁数が限られていますので, 実際には離散型一様分布からの抽出になっています.
MATLAB の rand 関数は, 区間 (0, 1) から(0 および 1 は含みません),実数を等確率で取り出します. 引数(関数に与える入力のこと)を空白にして
rand()
とすると,0 から 1 の範囲の実数がひとつ返されます. 一様分布から得られた乱数を 一様乱数(uniform random number)と呼びます.
一様乱数を成分とする行列を作るには, 行数と列数を rand 関数の引数に指定します(例題 ex2205a). 引数に整数値をひとつだけ指定すると,その次数の正方行列となります. たとえば,
rand(3)
とすると,
rand(3, 3)
と解釈されます.
ある区間の実数値ではなく,整数値(integer)の乱数を成分とした行列を作りたければ, randi 関数(テキストでは扱っていません)を使うとよいでしょう. 整数の下限値を a,上限値を b,行列の行数を n,列数を m とすると,
randi([a b], n, m)
とします.
どの値も出現確率が同じ一様乱数に対して,中心(0)付近の値が出やすく, 中心から離れるにしたがって出現確率が下がる乱数もよく使われます. 正規分布(normal distribution)をデータの発生装置とする 正規乱数(normal random number)です. 正規乱数を成分とする行列を作る MATLAB 関数は randn です. 使い方は rand 関数と同じです. 1.6.4 節で正規乱数を利用して相関のある2変数のデータを作り, 回帰分析を行いました.
1.6.4 節で解説したように,MATLAB は乱数の 種(seed)をもとに, ある決められたアルゴリズム(乱数発生器)を用いて乱数を生成します. 種が同じであれば,同じ乱数列が生成されます.
例題 ex2205c のプログラム1行目で乱数の種を設定していますが, この設定の書き方は現在の MATLAB では推奨されていません. かわりに, rng 関数(random number generation という意味)を用いて,
rng(2011)
としてください. 2011 という数値はテキストの出版年なので,変えてもかまいません.
設定された種を確認するには,引数なしで rng 関数を実行します. よって,例題 ex2205c のプログラム全体は以下のようになります.
rng(2011)
rng()
プログラム2行目は,括弧を使わず,単に rng
としてもかまいません.
2.2.6 等間隔な成分を持つベクトル:linspace, logspace
2.1.2 節で,初項,公差,末項を指定して, 成分が等差数列をなすベクトルを作る方法を学びました. MATLAB の linspace 関数(linear space という意味)では, 公差のかわりに成分の数を指定して, 成分が等差数列をなすベクトルを作ります. たとえば,
linspace(0, 1, 5)
とすると,初項が 0,末項が 1,成分の数が 5 の, 等差数列をなすベクトルが作られます.公差は 0.25 です. 同じベクトルは
0:0.25:1
として作ることができます.
これら2つの方法の違いは,linspace 関数を用いたときには, 第2引数として指定された数値が必ず数列の末項となるということです. たとえば,
0:0.25:1.1
linspace(0, 1.1, 5)
の結果を比較してください.最初の方法では, 0 に 0.25 を順に加えていってできる数列で, 1.1 を超えない最後の数(つまり,1)が末項となります. 第2の linspace 関数を使う方法では, 1.1 が末項となります.
MATLAB の logspace 関数は linspace 関数の対数バージョンです. ここで対数とは 常用対数(common logarithm)のことで, ある正の実数 が10の何乗であるかをあらわします. 記号で と書きます.たとえば,
,
です.
前出の linspace 関数が通常の意味で等間隔な数列(を成分とするベクトル)を作るのに対して, logspace 関数は対数的に等間隔な数列を作ります. すなわち,
logspace(a,b,n)
は, と の間で,対数をとったときに等間隔となる n 個の点を作成します. たとえば,
X = logspace(1, 4, 4)
とすると,10, 100, 1000, 10000 というベクトルが返されます(例題 ex2206b). このベクトルの成分の対数をとってみましょう. MATLAB の log10 関数は引数として与えられた実数の常用対数を返します. コマンドウィンドウで
X = logspace(1, 4, 4)
log10(X)
とキーインしてください.結果は下図のようになり, logspace 関数で作られたベクトル X の要素は対数的に等間隔であることがわかります.
テキストでは,対数グラフを描くときに logspace 関数が役立つと書いてあります. この具体例は,MATLAB のドキュメンテーションでの, loglog 関数(両対数スケール プロット)の解説にあります. ドキュメンテーションを開くにはコマンドウィンドウで doc とキーインしてください. ドキュメンテーションはウェブでも公開されています.
2.3 行列の演算
2.3.1 行列の加算と減算:+, -
行列の加算と減算は同じ型の行列同士でのみ可能です, 同じ型とは行列の行数と列数が等しいことです. 例題 ex2301a では,行列 A および B の型はいずれも2行3列です. 一般に,m 行 n 列の行列を 型の行列と呼びます.
行列の加算と減算は,同じサイズの行列同士で, 同じ位置にある要素での加算あるいは減算として定義されます. すなわち,m 行 n 列の2つの行列
について,
と定義されます.
数学では行列に対してスカラー(数)を加算あるいは減算することはできませんが, MATLAB ではそうした式を書くことができます(例題 ex2301b). スカラーを加えたり引いたりすると, 行列の各成分に対して加えたり引いたりした結果が得られます(テキスト p.52).
2.3.2 行列の乗算とスカラー倍:*
例題 ex2302a を用いて行列と行列の演算の定義を説明します. 2行3列の行列
と,3行2列の行列
の積 は,
という,2行2列の行列となります.
計算を順に行いましょう.最初に,下図のように, の第1行の成分と, の第1列の成分をひとつずつ順に取り出し, 対応する成分の積をすべて足し合わせます. この演算の結果が,行列の積 の 成分(第1行第1列の成分)となります.
次に, の第2行の成分と, の第1列の成分をひとつずつ順に取り出し, 対応する成分の積をすべて足し合わせます. この演算の結果が,行列の積 の 成分(第2行第1列の成分)となります.
ここまでは,第1章(1.6.1節)で説明した行列とベクトルの積
と同じです.
続いて, の第1行の成分と, の第2列の成分をひとつずつ順に取り出し, 対応する成分の積をすべて足し合わせます. この演算の結果が,行列の積 の 成分(第1行第2列の成分)となります.
最後に, の第2行の成分と, の第2列の成分をひとつずつ順に取り出し, 対応する成分の積をすべて足し合わせます. この演算の結果が,行列の積 の 成分(第2行第2列の成分)となります.
一般に, 型の行列 と, 型の行列 の積 は 型の行列であり, の 要素は の第 行と の第 行の積和となります. の列数と の行数が同じでないと,積 は計算できないということに注意してください.
積 と の結果は一般に一致しません.例題 ex2302a の行列 と では,
となります.
行列のスカラー倍(定数倍)は簡単で, 行列の各成分にそのスカラーをかけ算するだけです(例題 ex2302b).
2.3.3 行列の成分ごとの乗算:.*
第1章の 1.3.3 節で解説したように, ドット(.)つきの演算記号は,行列やベクトルの成分ごとに, (ドットなしの)演算を行うことを意味します.
例題 ex2303 では同じ型の行列 と について成分ごとの乗算を行っています. 一方をスカラー(定数)にすると,行列の成分ごとにスカラー倍することになりますね. たとえば
A = [1 2 3; 4 5 6]
C = A .* 2
とすると,行列 の成分それぞれが2倍されることになります. 2.3.2節で学習したように,行列のスカラー倍はドットなしの乗算記号(*)を用いて
A = [1 2 3; 4 5 6]
C = A * 2
と書くことができますから,
C = A .* 2
と
C = A * 2
は同じ演算を意味することになります.
そこでテキストでは,スカラー倍の演算記号として「*」のかわりに「.*」を用いてよく, むしろその方が安全であると述べています. 乗算の演算記号「*」は行列の乗算のための記号としてのみ使い, スカラー倍は「.*」を使うようにした方が, 意図と異なった演算をしてしまう危険を回避できるということですね.
2.3.4 行列の転置:', .'
例題 ex2304a に誤植がありました(改訂版第1刷). 正しくは
A = [1+i 2 3+4*i; 4 5-2*i 6], B=A', C=A.'
です.
複素数(complex number)については 1.2.6 節で学習しました.
数学で2次方程式の解の公式を習ったとき, 2乗するとマイナス1になる数をアルファベット小文字の で表しました.すなわち,
です.この数を 虚数単位(imaginary unit)と呼びます.
MATLAB では,i と j が虚数単位を表す記号です. コマンドウィンドウで,i^2 および j^2 とキーインしてみてください. いずれも という値が返されます.
と を実数として, と表される数を複素数と呼びます.
複素数 に対して, を 共役(きょうやく)複素数(conjugate complex number) あるいは複素共役と呼びます. の共役複素数は です.
行列の 転置(transpose)とは行列の行と列を逆にすることです. 行列の縦と横を入れ替えます. 行列 を転置してできた行列を 転置行列(transposed matrix)と呼び,記号 あるいは で表します.たとえば,
となります.行列 の第1行を第1列に, 第2行を第2列にすると,転置行列 となります.当然ですが,
となります.
成分が複素数の行列で,各成分を共役複素数に変える転置を 共役転置(conjugate transpose)と呼びます. 成分が実数の行列では,通常の転置と共役転置の結果は同じです.
2.3.5 行列の除算
1次方程式(linear equation)を行列とベクトルで表現して解く方法は 1.6.1 節で学習しました.たとえば,連立方程式
を行列とベクトルを使って表すと,
となります(例題 ex2305a).左辺は行列とベクトルの乗算で, ベクトルは行列の特別な場合(この例題では3行1列の行列)ですから, 2.3.2 節で学習した行列の乗算の定義が適用されます.
この式に現れる行列とベクトルを
と表すと,この連立方程式は
という形をしていることがわかります.これがスカラー(実数)についての方程式なら, の逆数 を用いて,
とすれば解くことができます. しかし,実際には は行列ですので, 逆数は存在しません.そこで,行列での逆数である 逆行列(inverse matrix)を使います. 行列 の逆行列を と書き,「 インバース」と読みます. 行列での 1 である単位行列(2.2.3 節参照)を と書くと,
となります.
逆行列を使って方程式 を解くと,
となります.これが式 (2.8) です.
MATLAB では inv 関数を用いて逆行列を求めることができます. そこで,例題 ex2305a の方程式を逆行列を用いて解くには,
A = [1 2 3; 4 5 6; 7 8 10];
b = [1 2 3]';
x = inv(A) * b
とします.ベクトル b は列ベクトルにすることに注意してください. 行列の乗算では交換法則は成り立たないので,最後の式を
x = b * inv(A)
とすることはできません.b は3行1列,inv(A) は3行3列なので, 乗算はできずエラーとなります(2.3.2 節参照).
行列とベクトルの1次方程式 は逆行列 を使って以上のように解くことができますが, MATLAB では異なった方法が推奨されています. それは行列の除算です(1.6.2 節参照).数学的では行列に除算は定義されていません. しかし,MATLAB では,あたかも
のような演算によって方程式を解くことができます.それには,
A = [1 2 3; 4 5 6; 7 8 10];
b = [1 2 3]';
x = inv(A) * b
にかえて,
A = [1 2 3; 4 5 6; 7 8 10];
b = [1 2 3]';
x = A \ b
とします(例題 ex2305a). ここで,A \ という表記が, A の逆行列を左からかけるという意味だと考えるとわかりやすいでしょう.
MATLAB での行列の除算を行う演算子は, 行列の左除算演算子(matrix left division operator)と呼ばれる \ と, 行列の右除算演算子(matrix right division operator)と呼ばれる / です. 日本語環境では,左除算演算子はバックスラッシュでなく, 「円マーク」であることに注意してください. 行列の除算演算子は逆行列を計算することなく方程式を解きます.
行列とベクトルの1次方程式はふつう という形をしていますが.もし という形をしていたら,行列の右除算演算子を用いて,
x = b / A
として解くことになります(例題 ex2305b). 数学での解は
ですから,逆行列 を右からかけるという意味だと考えるとわかりやすいでしょう. 例題 ex2305b で解いている方程式は
という方程式です.
2.3.6 最小2乗解:\, /
行列とベクトルの1次方程式 において行列 が正方行列でない場合には, 連立方程式での未知数の数と方程式の数が一致しないので, 解は不定(indeterminate)か不能(incompatible)となります. 「不定」とは解が一意でないこと,「不能」とは解が存在しないことを意味します.
行列が正方であっても,解が存在しなかったり,一意に定まらないことはあります. たとえば,連立方程式
を行列とベクトルを使って表すと
であり,行列は正方行列ですが,この方程式の解は不定です. なぜなら,連立方程式を構成している3つの1次方程式のうち, 第2の式の2倍から第1の式を引くと第3の式に一致してしまうためです. すなわち,この連立方程式は実質的に2つの1次方程式しかありません. 行列とベクトルで表すと
となります.この方程式の解は, を任意の実数として,
となります(この解は自力で求められなくてかまいません).
連立方程式の解が不能(解なし)の例も挙げておきます.連立方程式
は解がありません.なぜなら,第1の方程式と第2の方程式から が得られますが,これは第3の方程式 と矛盾するからです.
以上に述べた2例から, 個の未知数を含む 本の連立方程式 の解が不定あるいは不能になるのはどのような場合なのか, 気がつくのではないでしょうか. 正方行列 を構成する行ベクトルの中に, 他の行ベクトルから構成できてしまうものがあると, 方程式の解は不定あるいは不能となります. 上の例では,行列 の第3行が, 他の2行から構成できます(これはもちろん, 第1行は第2行と第3行から構成でき, 第2行は第1行と第3行から構成できることを意味します).
一般に,他からは構成できないベクトルの集まりは, 1次独立(linearly independent)であると言います. 他から構成できるベクトルが含まれている場合には 1次従属(linearly dependent)であると言います.
行列とベクトルの方程式 において, 型の正方行列 を構成する行ベクトルのうち, 1次独立である行ベクトルの最大個数を, この行列の 階数(rank)と呼びます. 行列の階数は MATLAB の rank 関数で求めることができます. 行列
および
の階数を求めてみてください.行列 の階数は 2, 行列 の階数は 3 となります.
個の未知数を含む 本の連立方程式 の解が一意に定まるのは,行列 の階数が のときです.
以下では,テキスト p.57 で述べられている最小2乗解について補足説明を行います.
連立方程式を構成する個々の方程式の数が変数の数よりも多くなると, 一般に解は存在しなくなります. 第1章の 1.6.4 節で学習した回帰分析はこうした状況の代表例です. 2変数 および について, 個( )の測定対象からデータ
が得られているとします. この2変数簡に1次関数で表される という関係があるとすると,この関係は
という連立方程式で書くことができます. もちろん,この連立方程式が解を持つのはすべての点 が直線上にあるときだけで,一般には解がありません. この方程式を行列の左乗算演算子(\)を用いて解くと, 最小2乗解(least squares solution) が得られます.これは,直線上の点を
とすると, 2乗誤差(square error),すなわち, 実際のデータとの誤差の2乗和
を最小にする傾き()と切片()です. テキスト p.57 の式 (2.12) の表記では, 個の誤差は
と
の差
であり,誤差を成分とするベクトルで表現されています.このベクトルの大きさ は
となります.ベクトルの成分が2つのときは,これはピタゴラスの定理(三平方の定理)です. このベクトルの大きさの2乗は
であり,右辺は2乗誤差となっています. 誤差を成分とするベクトルの大きさの2乗は,2乗誤差(誤差の2乗和)になるということがわかります.
列ベクトルである
の大きさの2乗は,式 (2.12) のように,
という計算によって得られます. ここで は転置の演算で(2.3.4 説参照), 列ベクトルを行ベクトルにしています.
最小2乗解についての補足説明は以上です.
テキスト p.57 の2行目の 「行列 の階数 が最大でないとき」 という記述の意味はわかりにくいです. これは,連立方程式を構成する個々の方程式の数が, 未知数の数よりも少ないことを意味しているようです. たとえば,方程式
では,未知数の数は3で,連立方程式を構成する方程式の数は2です.
この方程式での行列の階数 は2です. これは連立方程式を構成する個々の方程式の数に一致しています. 未知数の数が3なので,連立方程式が一意な解を持つためには, 階数が3の正方行列が必要です. テキストではこの状況を 「行列 の階数 が最大でないとき」 と述べているようです.
この方程式は解を持ちますが(つまり,2乗誤差を 0 にする解がありますが), 一意に定まりません. 解のひとつは,未知数のうちひとつの値を 0 にして, 未知数と方程式の数をいずれも2つにすることで求められます. たとえば, とすると,
となるので,
という解が得らえます. こうした解を MATLAB で得るには行列の除算演算子を用います. たとえば,
A = [1 2 3; 4 5 6];
b = [1 3]';
r = rank(A)
format rat % 出力表示形式を分数に
x = A \ b
format short % 出力表示形式をもとに戻す
というコードを実行してください. 以下のように解が得られます. 方程式が不足している数だけ未知数の値を 0 にしますので, テキストで述べられているように, 「たかだか 個の零でない成分を持つ解を与えます」 という結果になります.
未知数が3つ,方程式がひとつの例が,例題 ex2306a です. 2つの未知数の値が 0 にされています.
テキスト p.57 の中ほどで述べられている 一般化逆行列(generalized inverse)とは, その名のとおり,逆行列の概念を拡張したものです. 逆行列は正方行列についてのみ存在しますが(ただし, 逆行列を持たない正方行列もあります), 一般化逆行列は任意の型の行列について存在します. MATLAB では pinv 関数を用いて一般化逆行列を求めることができます.
解が不定あるいは不能な方程式を解くために一般化逆行列を用いることができます. たとえば,第1章での回帰分析の例題 ex1604a において(p.29), 5行目の
AB = Xm \ Ym;
を
AB = pinv(Xm) * Ym;
に変えても同じ結果が得られます.
式 (2.13) に誤植があります(改訂版第1刷). 転置するのは後の方のベクトルであり,正しくは
となります.最後の転置演算の記号 は,テキストでは小文字です. 小文字だとべき乗に見えるので,ここでは大文字にしました.
2.3.7 行列の成分ごとの除算:.\, ./
2.3.3 節で行列の成分ごとの乗算を学びました. 2.3.7 節は行列の成分ごとの除算です.乗算が除算に変わっただけなので, 理解は容易でしょう.
式 (2.14) の行列 および は同じ型です. 型が同じでないとエラーになります.
例題 ex2307 の行列 および は
C = B ./ A
D = B .\ A
と書くこともできます.
2.3.8 行列のべき乗:^
MATLAB では,正方行列 について,
A * A
A * A * A
A * A * A * A
のかわりに
A^2
A^3
A^4
と書くことができます.数学では正方行列のべき乗を
と書きますので,この表記が MATLAB でも使えるということです.
実数 の 0 乗が 1 と定義されるのと同様に, 正方行列 の 0 乗は同じ次数の単位行列 であると定義されます. すなわち,
です.これを確認するため MATLAB で
A = [1 2 3; 4 5 6; 7 8 9]
A^0
というコードを実行してみてください.3次の単位行列が返されます
面白いのは,MATLAB ではべきの数が整数でなくてもよいところです. たとえば,
A = [1 2 3; 4 5 6; 7 8 9];
C = A^0.5
とすると, となる行列 が得られます. 上のコードに続いて,
C^2
としてこれを確かめてください.
2.3.9 行列の成分ごとのべき乗:.^
行列の成分ごとのべき乗は,成分ごとの乗算(2.3.3 節),および, 成分ごとの除算(2.3.7 節)と類似しています. 理解は容易でしょう.
2.3.10 行列の成分ごとの論理演算:|, &, ^, XOR
論理値(logical value)とは命題の真偽を表す数値です.命題が 真(TRUE)であることを 1 で, 偽(FALSE)であることを 0 で表します.
プログラミングでは, ある条件が成立しているかどうかのテストがよく行われます. このテストの結果を表すとき,論理値が用いられます. 成立していれば 1,成立していなければ 0 です. これについては次の 2.3.11 節,および,第3章で学習します.
MATLAB では. 論理値についての演算として, 論理和(logical disjunction), 論理積(logical conjunction), 否定(not / inversion), 排他的論理和(exclusive disjunction) の4つが用意されています.このうち,否定は単独の論理値についての演算です. あとの3つは2つの論理値についての演算です.
否定(NOT)の演算子は ~ です.これは論理値を「ひっくり返し」ます. すなわち,
~0
は論理値の 1 を返し,
~1
は論理値の 0 を返します.
否定の演算子はプログラミングで「・・・ではないとき」という条件を書くときに便利です. 実例として,第3章で学習する例題 ex3602 があります.
論理積(AND)の演算子は & です.2つの論理値の両方が 1 の場合のみ 1 を返し,そのほかの場合は 0 を返します. すなわち,
0 & 0
1 & 0
0 & 1
1 & 1
という4つの演算を行うと,最初の3つの結果は 0 となり, 最後の演算だけが 1 という結果になります. MATLAB のコマンドウィンドウで試してみてください.
論理積は2つの条件がともに成立しているかどうかをテストしたいときに使います.
論理和(OR)の演算子は | です.2つの論理値の一方あるいは両方が 1 の場合に 1 を返し,両方が 0 の場合は 0 を返します. すなわち,
0 | 0
1 | 0
0 | 1
1 | 1
という4つの演算を行うと,最初の演算の結果は 0 となり, あとの3つの演算は 1 という結果になります.
論理積は2つの条件のうちいずか一方が成立しているかどうかをテストしたいときに使います. 両方が成立していてもいいです.
排他的論理和(XOR)の演算を行うには関数 xor を用います.この関数は,2つの論理値の一方だけが 1 の場合に 1 を返し,両方が 0 の場合は 0 を返します. すなわち,
xor(0, 0)
xor(1, 0)
xor(0, 1)
xor(1, 1)
という4つの演算を行うと,最初と最後の演算の結果は 0 となり, あとの2つの演算は 1 という結果になります.
論理積は2つの条件のうちいずか一方「だけ」が成立しているかどうかをテストしたいときに使います.
MATLAB では,以上4つの論理演算を,ベクトルあるいは行列に対して適用することができます. ベクトルへの適用例が例題 ex2310 です. 否定はひとつのベクトルあるいは行列に適用されます. 論理和,論理積,排他的論理和では,2つの行列の型が同じでなければなりません. ただし,一方がスカラーの場合は,行列の各成分とそのスカラーとの論理演算が行われます. 一方が 型でもう一方が 型の場合と,一方が 型でもう一方が 型の場合も論理演算が実行できます.実験してみてください.
論理演算において,0 以外の数はすべて 1 と見なされます. たとえば,例題 ex2310 での2つのベクトルを
A = [0 0 2 2];
B = [0 3 0 3];
と変えてみてください.結果は例題 ex2310 と同じになります.
2.3.11 行列の成分ごとの関係演算:==, ~=, <, <=, >, >=
関係演算子(relational operator)を用いた関係演算は, 特定の関係が成立しているかどうかをテストします. 成立していれば論理値の 1 を,成立していなければ論理値の 0 を返します. たとえば,
A = 1;
B = 2;
A == B
というコードは「A と B は 等しい」という関係が成立しているかどうかをテストしており, この場合は成立していないので 0 が返されます.
特定の関係が成立しているかどうかのテストは,プログラミングにおいて頻繁に必要となります. これについては第3章で学習します.
2.3.12 内積:dot
高校数学では,2つのベクトル と の 内積(inner product) を,ベクトルの大きさ および と,2つのベクトルのなす角 を用いて,
と定義しました. ベクトルの内積として得られるのはベクトルではなくスカラーであることに注意してください.
2つのベクトルの成分を
とすると,内積はベクトルの成分を用いて表すことができ,
となります.
MATLAB では dot 関数を用いてベクトルの内積を計算することができます(例題 ex2312).
ベクトルは行列の特別な場合ですから, 行列の乗算によって内積を求めることもできます. たとえば,2つの列ベクトル
の内積は,
によって求めることができます. これは 型の行列と 型の行列の乗算になっています.結果は 型の行列すなわちスカラーになります.
例題 ex2312 で,dot 関数のかわりに行列の乗算によって内積を求めるのならば,
X = 1:3
Y = 3:-1:1
Z = X * Y'
とします.この場合,2つのベクトルは行ベクトルなので, 第2のベクトル Y を転置して列ベクトルにしています.
2.4 行列の処理
2.4.1 行列の成分を取り出す:( )
ベクトル の 番目( ) の要素を取り出すには
X(i)
とします.
型の行列 の, 第 行 列( , )の要素を取り出すには,
A(i, j)
とします.
2.4.2 成分を追加する
例題 ex2402 の行列 は2行2列ですから. 単に
A(3, 4);
とするとエラーになります.しかし.少し奇妙なのですが,
A(3, 4) = 9;
とすると,行列が拡張され, 成分が 9 となります. 拡大によって追加されたその他の成分は 0 となります.
成分の追加ではなく,成分の変更も同じ方法を使います. たとえば,例題 ex42402 の行列 の 成分を 4 から 9 に変更したければ,
A(2,2) = 9;
とします.
2.4.3 行列から行や列を取り出す::
例題番号の ex2603b は 2403b の誤植です(改訂版第1刷).
例題 ex2403a を見れば理解できると思いますが, テキストの説明は少しわかりにくいかもしれません.
行列から特定の行を取り出すには,成分を取り出すとき(2.4.1 節)と同じ方法でその行を指定し, 列の指定を「:」とします.同様に, 行列から特定の行を取り出すには,その列を指定し,行の指定を「:」とします. 特定の行を取り出すと行ベクトルが,列を取り出すと列ベクトルが得られます.
複数の行あるいは列を取り出したいときには, それらをベクトルで指定します. 例題 ex2403a では,
Z = A(:, 1:3)
として,行列 の1列目から3列目を取り出しています. この指定は
Z = A(:, [1 2 3])
と書くこともできます.
例題 ex2403b の4行目の
D = A(L, M)
という指定は,行と列の指定の両方がベクトルなので, 少しわかりにくいかもしれません. ベクトルの成分を明示すると
D = A([1 4], [2 3])
となります.これがどのような操作なのか, 行の取り出しと列の取り出しに分けて, 2段階で考えるとわかりやすいかもしれません.
まず第1段階として,[1 4] という行の指定により, 行列
の1行目と4行目が取り出されます. すなわち,
という行列が得られます.
第2段階として,[2 3] という行の指定により, この行列の2列目と3列目が取り出されます. その結果,
という行列が得られます.
2.4.4 行や列を追加する
本節と 2.4.7 節では,ベクトルあるいは行列を積み木のように重ねて, より大きな行列を構成できることを示します. このとき,積み木に「はみ出す」部分があるとエラーになります.
例題 ex2404 では, 型の行列 の下に, 成分数が3の行ベクトルを加えています. 積み木の横幅がいずれも3なので,こうした合成が可能です.
2.4.5 行または列を取り除く
行または列を取り除く方法を説明する前に, 特定の行あるいは列を変更する方法を説明します.
2.4.2 節で,行列の成分を変更する方法を説明しました. これと同じ方法で, 特定の行あるいは列の全体をまとめて変更することができます. 変更後の値をベクトルで表し,その行あるいは列に代入します. たとえば,
という行列を作るつもりだったのが,
A = [1 2 3; 1 2 3; 7 8 9; 10 11 12];
というように入力を誤って,
という行列を作ってしまったとします. 2行目を変更するには,
A(2, :) = [4 5 6];
とします.
特定の列を変更したい場合も同じ方法を使います. このとき,変更後の値は列ベクトルと行ベクトルのどちらで表してもかまいません.
特定の行あるいは列の変更後の値として, 成分が空白のベクトルを指定すると, その行あるいは列が削除されます. いくつかの行あるいは列をまとめて削除することもできます. 例題 ex2405 をやってみてください.この例題のコードの1行目では, 削除する行がベクトルで
A(:, [2]) = []
と書かれていますが,これはスカラーで
A(:, 2) = []
と書けばよいでしょう.
2.4.6 行や列を逆順に並べ替える
行あるいは列の並べ替えは,2.4.3 節で学習した, 特定の行や列を取り出す方法の応用です. 逆順に限らず,どのような並べ替えもできます.たとえば, 例題 ex2406 の行列 の, 1行目と4行目を入れ替えた行列を作るには,
A([4 2 3 1], :)
とします.
2.4.7 小さな行列から大きな行列を作る
2.4.4 節で説明したように,ベクトルあるいは行列を積み木のように重ねて, より大きな行列を構成することができます. このとき,積み木に「はみ出す」部分があるとエラーになります.
2.4.8 行列の成分に施す関数
例題 ex2408 では行列の各成分に sqrt 関数が適用されています. 1.8.2 節にある他の関数を用いた例を作ってみてください.
2.5 文字列を扱う
2.5.11 節と 2.5.12 節はスキップしてかまいません.
2.5.1 文字列を作る:', char
テキストでは,一連の文字をシングルクォーテーション('),あるいは, ダブルクォーテーション(")で囲んで文字列を作成すると書かれていますが, これは不正確です.このテキストが発行された2011年の時点では,シングルクォーテーションのみが使用でき, ダブルクォーテーションは使用できませんでした. MATLAB 2016b 以降では,シングルクォーテーションとダブルクォーテーションが使用できますが, 違いがあるので注意が必要です.
一連の文字(character)をシングルクォーテーションで囲むと, 文字配列(character array)が作成されます. ダブルクォーテーションで囲むと string 配列(string array)が作成されます. 例題 ex2501a で,文字列をシングルクォーテーションで囲んだ場合と, ダブルクォーテーションで囲んだ場合を比較してみてください.たとえば,
X1 = 'MATLAB ver.7.0'
X2 = "MATLAB ver.7.0"
whos
とすると,以下のように表示がされます. X1 は28バイトを使用した1行14列の文字配列であるのに対して, X2 は166バイトを使用した1行1列の string 配列であることがわかります. テキストでは whos 関数, size 関数,class 関数の3つを使用していますが, whos 関数が返す情報は size 関数と class 関数が返す情報を含みます.
文字配列 'MATLAB ver.7.0' のサイズが1行14列ということは, 文字それぞれは別々の要素であるということです. エクセルのような表計算ソフトウェアで考えると, 各セルにひとつの文字が入力された,下図の状態です.
これに対して,string 配列では文字列がひとまとまりにされています. エクセルのような表計算ソフトウェアで考えると, ひとつのセルに文字列全体が入力された状態に相当します.
この違いは例題 ex2501b でよりはっきりします.
文字配列を行列に並べる場合,スペースを入れて文字列のサイズをそろえないとエラーとなります.
このエラーは,[1 2; 3 4 5]
というように,
サイズの違うベクトル(成分は数値)を並べて行列を作ろうとしたときのエラーと同じです.
一方,string 配列は文字列全体がひとつにまとめられているので,
X = ["MATLAB ver.5.0"; "MATLAB ver.7.0.1"]
はエラーになりません.
これ(X)は string 配列を並べた配列となります.
X2 = "MATLAB ver.7.0"
のように作られる string 配列は,1行1列の string 配列です. 1行1列の string 配列を string スカラー(string scalar)と呼びます. 実数を成分とする1行1列の行列をスカラーと呼ぶのと同じです.
注意:以下では,string 配列は扱わず,文字配列だけを扱います.
例題 ex2501c および ex2501d で使用している char 関数は文字配列を作成します. 引数として複数の文字配列を並べると(引数なのでコンマで区切って並べます), これら文字配列を各行とした行列が作成されます.
2.5.3 節で学習するように,char 関数は数値から文字への変換にも使用されます.
2.5.2 文字列を取り出す:deblank
関数名 deblank は delete blank という意味です. 各行が文字配列である行列は,各行のサイズをそろえるために, 必要に応じてスペース(空白文字)が最後に挿入されているのでした(例題 ex2501b を参照). この空白文字を除去するために deblank 関数を使用します.
例題 ex2502 では,行列(2行1列の文字配列)の1行目は,
MATLAB ver.5.0
という14文字の後に空白文字が2つある,
16文字(1行16列)のベクトル(文字配列)です.
この行を Y = X(1,;)
としてそのまま取り出すと,
length 関数によって返されるベクトルの成分数は 14 + 2 で 16 となります.
文字列を取り出すときに Z = deblank(X(1,;))
として空白文字を消去すると,
成分数は 14 となります.
なお,MATLAB
と ver
の間にある空白文字は消去されません.
2.5.3 文字列と ASCII コード:double, char
コンピュータのメモリ上で,文字は数値で保存されています. ディスプレイ上では,メモリ上の数値に対応する文字を表示します. このようなことが可能なのは, 扱いたい文字の集合(文字集合)が定義されており, それぞれの文字に数値(コード)が割り当てられているからです. 割り当てられた数値あるいは割り当て規則を文字コードと呼びます.
ASCII コードは,American Standard Code for Information Interchange という意味であり, 英語圏で使用する128文字(数字や記号を含む)に数値が割り当てられています.
テキストの記述では MATLAB の文字コードが ASCII コードであるように読めますが, これは不正確です. MATLAB では,Unicode と呼ばれる,ASCII コードよりも大きな文字集合が用いられています. ここには日本語も含まれます.
文字がどのような数値でメモリ上に保存されるかを調べるには double 関数を用います. 逆に,メモリ上の数値に対応する文字を調べるには char 関数を用います.
ややこしいですが,数字と数値は区別してください. たとえば,'MATLAB ver.7.0' という文字配列での '7' および '0' は数字であって, 文字の一種です.コマンドウィンドウで
double('7')
double('0')
とキーインすれば,数字の '7' は 55 という数値で, 数字の '0' は 48 という数値でメモリ上に保存されることがわかります. 続いて,
char(55)
char(48)
という逆の変換もやってみるとよいでしょう.
数値は四則演算が可能ですので,double 関数が返す数値は四則演算に使うことができます. たとえば,
char(double('A') + 32)
とキーインしてみてください.小文字の 'a' が返されます. アルファベットの大文字と小文字は文字コードの数値で 32 離れているので, このような結果になります.
2.5.4 文字列を比較する:strcmp, strncmp
2つの文字配列列全体が等しいかを調べる strcmp 関数は string comparison という意味です. 最初の n 文字まで等しいかどうかを調べるには strncmp 関数を使います.
2.5.5 文字を比較する:==
関係演算子のひとつである == は 2.3.11 節で学習しました. そのときは数値の比較を行いましたが, ここでは文字を比較するためにこの演算子を用います. コンピュータのメモリ上で文字は数値で保存されている(2.5.3節)ということを知っていれば, 同じ演算子で文字の比較ができることは不思議なことではないでしょう. 以下のように,いくつかの比較を試してみるとよいでしょう. 文字を引用符(')で囲むことを忘れないようにしてください.
'a' == 'b'
'a' ~= 'b'
'a' >= 'b'
'a' <= 'b'
関係演算子を文字ではなく文字配列に適用すると, 文字配列を構成する文字ごとに比較が行われます(例題 ex2505). 比較される文字配列の長さは等しくなくてはいけません. 一致していないとエラーとなります.
例題 ex2505 での C = (S == T)
という記述の意味は少しわかりにくいかもしれません.
最初に,S == T
が実行され,
文字配列 S と T の比較が行われます.
文字配列は4つの文字から構成されているので,
比較の結果は要素の数が4つのベクトルとなります.
このベクトルが変数 C
に代入されます.
比較演算子 == を用いると, 組み込み関数 strcmp および strncmp と同一の動作をする関数を定義することができます. 練習問題としてやってみましょう. 組み込み関数と区別するため, MyStrcmp および MyStrncmp という関数名で定義を書いてみてください.
2.5.6 文字列を分類する:isletter, isspace
文字配列中の文字それぞれがアルファベットであるかどうかを判定する isletter 関数の名前は, Is it a letter (or not)? という問いであると考えるとわかりやすいでしょう. 文字配列中の文字それぞれがスペースであるかどうかを調べる isspace 関数も同様です.
2.5.7 文字列を検索する:findstr
関数名 findstr は find string という意味です.
例題 ex2507 では,
findstr(X, 'MAT')
findstr(X, 'LAB')
も試してみてください.文字配列の中で指定した文字列が見つかると, その先頭要素の位置が返されることがわかります,
2.5.8 文字列を置換する:strrep
関数名 strrep は string replace という意味です. 例題 ex2508 で,関数の動作は簡単に理解できるでしょう.
2.5.9 数値を文字列に変換する:int2str, num2str
MATLAB の最近のバージョンでは,例題 ex2509 での size 関数は不要です. 以下のようにスクリプトを書いて実行してください.
X = 100 .* rand(2, 3)
Y = int2str(X)
Z = num2str(X, 5)
結果は下図のようになります(乱数を使っているので,同じ結果にはなりません).
変数 X に保存されているのは,実数を成分とする,2行3列の行列です.
この行列の大きさは size(X)
とキーインすれば得られます.
変数 Y に保存されているのは2行10列の文字配列です. 変数 X に保存されている行列の要素(実数)を, int2str 関数(integer to string という意味)によって文字配列に変換しました. この関数は整数を文字に変換する関数です.入力が整数でなく小数点以下のある実数の場合には, 変換の前に小数部分が四捨五入されます.
変数 Y に保存されている文字配列は,各行に空白文字が入っていることに注意してください. たとえば,上図の 17 と 3 の間には3つ,71 と 28 の間には2つの空白文字が入っています. そのため,見えている文字数よりも,列数は大きくなっています.
変数 Z に保存されているのは2行30列の文字配列です. 変数 X に保存されている行列の要素(実数)を num2str 関数(number to string という意味)によって文字配列に変換しました. ここでも,各行に空白文字が入っていることに注意してください.
これまでに学習した文字配列を扱う関数う関数と異なり, int2str 関数,および,num2str 関数は,どのようなときに役立つのかよくわからないと思います.
これらの関数は,数値として得られている結果を, 文字列として表示したいときに役立ちます. たとえば,以下のスクリプトを書いて実行してみてください(ex2509b というファイル名で保存します).
A = input('預金する金額(円):');
R = input('金利(%):');
N = input('預入期間(年):');
F = A * (1 + R/100).^N;
disp([num2str(F), '円になります.']);
預金する金額,金利,預入期間をたずねられますので, 適当な数値を入力してください.たとえば, 預金する金額を100,000円,金利を0.1%,預入期間を10年とすると, 10年後の金額が以下のように表示されます.
メッセージの表示に使用している disp 関数は 3.4 節で学習します. メッセージ中で,num2str 関数により,変数 F に保存されている数値を文字に変換しています. 例題 ex2509 では num2str 関数の第2引数で桁数を指定していましたが, ここではその指定を行っていません.
2.5.10 文字列を数値に変換する:str2num
文字配列を数値配列に変換する str2num 関数は, num2str 関数と入出力関係が逆となる関数です.
どのようなときに str2num 関数が役立つのか,やはりわかりにくいですね. ひとつの例として,第7章の例題 ex7103 のように, 入力ボックスを表示して数値を入力してもらう場合があります. 入力情報はすべて文字として保存されるので, これを数値として扱うには str2num 関数で数値に変換する必要があります. 第7章で例題 ex7103 を学習するときにやってみましょう.
2.5.11 基底変換
本節以降はスキップして,第2章の学習を終えてもらってかまいません.
本節での関数の名前は,decimal number(10進数),hexadecimal number(16進数), binary number(2進数)に由来します.
10進数からの基底変換,および,10進数への基底変換では, 数値と文字配列の間で変換が行われることに注意してください. たとえば,10進数から2進数への変換を行う dec2bin 関数は, 数値を成分とする行列(あるいは,スカラー)を引数にとり, 変換後の2進数は文字配列で表されます. この逆の変換を行う bin2dec 関数は, 2進数を表す文字列から構成される文字配列を引数にとり, 10進数の数値を返します.例題 ex2511 を参照してください.
発展事項を補足しておきます. 10進数から2進数への変換では,文字配列ではなく, 数値としての 0 と 1 を並べたベクトルが欲しいこともあります. たとえば,10進数の 5 を2進数に変換するとき, dec2bin 関数は '101' という文字列を返しますが, そうではなく [1 0 1] というベクトルが欲しいことがあります. このような場合には,bitget 関数を利用して,
bitget(5, fix(log2(5))+1:-1:1) # bitget(5, 3:-1:1) と同じ
とすれば,[1 0 1] というベクトルを得ることができます. この関数は,第1引数として与えられた整数を2進数に変換したときの, 第2引数で指定された位置(桁)にある値(0 あるいは 1)を返します.
ベクトルで表された2進数はいろいろなことに利用でき,価値が高いものです. 例として,統計学での符号つき順位和検定(Wilcoxon signed rank test)での, 順位和の確率分布を求めるスクリプトを以下に示します. 第3章で学習する for 文による繰り返し処理を行っています.
N = 6; % 6組の対応あるデータの場合
T = zeros(1,N*(N+1)/2 + 1); % 順位の合計値の分布を表すベクトルを用意
W = zeros(N, 2^N); % 0 から 2^N - 1 までの2進数を並べる行列を用意
for I = 0:(2^N)-1
W(:, I+1) = bitget(I, 1:N);
end
S = (1:N) * W; % 順位の組み合わせすべてについて,順位の合計を計算
% 順位和それぞれの出現回数の分布を得る
for J = 1:length(S)
T(S(J)+1) = T(S(J)+1) + 1;
end
Ps = [0:n*(n+1)/2; T/2^n] % 順位和の確率分布(1行目が順位和,2行目が確率)
2.5.12 文字列を実行する
数値を要素とする行列を文字配列に変換する関数として, 2.5.9 節では int2str 関数と num2str 関数を学習しました. 2.5.12 節では,類似の変換を行う mat2str 関数を学びます. これら3つの関数の違いを確認しましょう. コマンドウィンドウで,以下のコードをキーインしてください. 最終行の mat2str 関数は第2引数で精度(変換後の桁数)を指定しています.
A = 100 .* rand(2, 3)
S1 = int2str(A)
S2 = num2str(A)
S3 = mat2str(A, 6), size(S3)
文字配列 S1 から S3 の内容は以下のように表示されます.
行列 A は数値(乱数)を要素とする2行3列の行列です. この行列を int2str 関数あるいは num2str 関数で文字配列に変換すると, 行列の形は維持されています. すなわち,1文字あたり1列を使うので列数は行列 A と異なりますが, 行数は2行で同じです. これに対して,mat2str 関数による変換では, 行列 A は1行の文字配列に変換されています.
例題 ex2512 の解説で述べられているように, 行列 A を mat2str 関数で変換して得られた文字配列はプログラムの形式になっています. つまり,この文字配列の内容をコマンドウィンドウでキーインすると, 行列 A が得られます.
プログラム形式になっている1行の文字配列は eval 関数で実行できます. セクションタイトルの「文字列を実行する」はこのことを意味しています. この関数名は evaluate(評価する)に由来します.
このセクションで学習した mat2str を用いたおもしろいプログラムを PlugOut さんのブログ記事で見つけたので紹介しておきます. A から E までの5文字から3文字を選ぶすべての組み合わせを表示するプログラムです.
data = ["A", "B", "C", "D", "E"];
patterns = nchoosek(data, 3);
[m, ~] = size(patterns);
for i = 1: m
pattern = patterns(i, :);
disp(mat2str(pattern));
end