行列の四則演算
以下は1995年から1999年までの1月から12月までの平均黒点数のデータです。data1.txtに格納されているとしましょう。
11 4 9 4 5 11 8 14 1 0 17 13
5 7 8 15 18 12 10 24 51 23 39 41
31 40 54 53 56 70 66 92 92 55 74 81
62 66 68 63 106 137 113 93 71 116 133 84
横軸が1月から12月、縦軸が1995年から1999年までの5年間になります。次のデータは2001年から2004年までの同じく黒点数データです。こちらはdata2.txtに格納されているとします。
95 80 113 107 96 134 81 106 150 125 106 132
114 107 98 120 120 88 99 116 109 97 95 80
79 46 61 60 54 77 83 72 48 65 67 46
37 45 49 39 41 43 51 40 27 48 43 17
この2つの行列データですが、単純に同じ升目同士を足したり、引いたり、掛けたり、割ったりしたいことがあります。行列の四則演算ですね。表計算でも面倒なセル設定が必要ですし、rpnを使うとこれも結構大変です。
行列データの四則演算の考え方
そこで、rpnマイスターパッケージに用意したのは、同じ形の行列同士の四則演算プログラムです。具体的にはplus、minus、times、divideプログラムです。
計算の仕方は簡単で、行列同士を横に繋げて計算します。例えば行列1と行列2が以下のようになっているとします。
1 2 3
4 5 6
行列2
6 5 4
3 2 1
これらを横に繋げます。すると以下のようになります。
1 2 3 6 5 4
4 5 6 3 2 1
この繋げた2つの行列データをplusやminusといった行列用の四則演算プログラムに渡すことで一気に計算してくれます。
7 7 7
7 7 7
このように行列1の1と行列2の6を足して7、行列1の2と行列2の5を足して7、…のように一発で計算してくれます。ただし、四則演算する行列同士は同じ形である必要があります。
行列データの「+-×÷」
では、上記の黒点数のデータdata1.txtとdata2.txtを横に繋げて計算してみましょう。以下のようにdata1.txtとdata2.txtを横に繋げたデータを、そのままplusプログラムに渡します。
行列データの「+」
>rpn <data1.txt >tmp>rpn <data2.txt >>tmp
>rpn 2 -c paste <tmp | rpn -c plus
114 141 169 139 135 139 184 144 120 120 115 114
106 84 122 111 101 145 89 120 151 125 123 145
119 114 106 135 138 100 109 140 160 120 134 121
110 86 115 113 110 147 149 164 140 120 141 127
99 111 117 102 147 180 164 133 98 164 176 101
計算結果が出ています。面倒な手作業が一切不要で一発で計算できていますね。同じように引き算、掛け算、割り算を計算してみましょう。
行列データの「-」
>rpn 2 -c paste <tmp | rpn -c minus-66 -83 -107 -111 -107 -109 -156 -116 -98 -78 -97 -94
-84 -76 -104 -103 -91 -123 -73 -92 -149 -125 -89 -119
-109 -100 -90 -105 -102 -76 -89 -92 -58 -74 -56 -39
-48 -6 -7 -7 2 -7 -17 20 44 -10 7 35
25 21 19 24 65 94 62 53 44 68 90 67
行列データの「×」
>rpn 2 -c paste <tmp | rpn -c times2160 3248 4278 1750 1694 1860 2380 1820 1199 2079 954 1040
1045 320 1017 428 480 1474 648 1484 150 0 1802 1716
570 749 784 1800 2160 1056 990 2784 5559 2231 3705 3280
2449 1840 3294 3180 3024 5390 5478 6624 4416 3575 4958 3726
2294 2970 3332 2457 4346 5891 5763 3720 1917 5568 5719 1428
行列データの「÷」
>rpn 2 -c paste <tmp | rpn -c divide0.266667 0.258929 0.224638 0.112 … 0.100917 0.212121 0.0849057 0.0961538
0.115789 0.05 0.079646 0.0373832 … 0.00666667 0 0.160377 0.0984848
0.0438596 0.0654206 0.0816327 0.125 … 0.46789 0.237113 0.410526 0.5125
0.392405 0.869565 0.885246 0.883333 … 1.91667 0.846154 1.10448 1.76087
1.67568 1.46667 1.38776 1.61538 … 2.62963 2.41667 3.09302 4.94118
最後のdivideプログラムの結果は横に長すぎるため省略してあります。
ここで、引き算と割り算には注意が必要です。minusプログラムは向かって左の行列から右の行列を引いていることが分かると思います。data1.txtからdata2.txtを引いているわけですね。divideプログラムの割り算も同様なので、後の行列データに0があるとエラーが発生します。
普通の表記の「1÷2」も逆ポーランド表記の「1 2 /」も共に先の数値を後の数値で引いたり割ったりしているので、それに合わせてあるためです。
行列データの拡大・縮小と増減
行列データの四則演算で行列の計算が一気に楽になりましたが、実際に行列のデータを扱っていると行列内の全部の数値を数倍したいとか数分の一にしたいということがあります。
rpnマイスターパッケージではそのような要求に応えるためにoffsetとscaleプログラムを用意しています。まずは一定数を行列データの全ての数値に乗じるscaleプログラムの使用例です。
48 58 62 28 28 30 28 28 22 42 18 20
22 8 18 8 10 22 16 28 2 0 34 26
10 14 16 30 36 24 20 48 102 46 78 82
62 80 108 106 112 140 132 184 184 110 148 162
124 132 136 126 212 274 226 186 142 232 266 168
data1.txtの全ての数値を2倍しています。次は行列内の全ての数値に1を加えるoffsetプログラムの使用例です。
25 30 32 15 15 16 15 15 12 22 10 11
12 5 10 5 6 12 9 15 2 1 18 14
6 8 9 16 19 13 11 25 52 24 40 42
32 41 55 54 57 71 67 93 93 56 75 82
63 67 69 64 107 138 114 94 72 117 134 85
説明の必要はありませんね。scaleプログラムを使うと行列データの全ての数値の符号反転ができますし(-1を掛ける)、offsetプログラムを使うと比率計算後に増減比率を計算できます(-1を加える)。
行列データの小数点の扱い
次に小数点の扱いについて示します。divideの計算結果にあるように小数点以下が多くある場合は見づらいですし、実際にそこまでの小数は不要なことが多いです。そんなときは行列データの数値の小数を特定の桁数で一気に切り捨ててくれると便利です。
rpnマイスターパッケージのdecimalは指定された小数点以下を切り捨てるrpnプログラムです。以下の例では前出のdivideで計算した結果をデータとして、decimalプログラムに渡しています。
0.26 0.25 0.22 0.11 0.11 0.12 0.08 0.1 0.1 0.21 0.08 0.09
0.11 0.05 0.07 0.03 0.05 0.08 0.09 0.13 0 0 0.16 0.09
0.04 0.06 0.08 0.12 0.15 0.13 0.1 0.2 0.46 0.23 0.41 0.51
0.39 0.86 0.88 0.88 1.03 0.9 0.79 1.27 1.91 0.84 1.1 1.76
1.67 1.46 1.38 1.61 2.58 3.18 2.21 2.32 2.62 2.41 3.09 4.94
きれいに小数点の桁数2より下がカットされていますね。
pasteはユーティリティパッケージに同梱されています。
本講座で使用したプログラムは、rpnマイスターパッケージとして購入することができます。xypとnpdはrpnの姉妹ソフトウェアです。詳しくはプロダクトを参照ください。