[MATLAB]初心者が初見で必ずthinking顔になるもの特集

JavaScript初心者向けの良記事「[[JavaScript]初心者が初見で必ずthinking顔になるもの特集](https://qiita.com/kozzzz/items/b4cd57ead41fc6355afd)」を見た瞬間に、「<b>あっ…これMATLABでもめっちゃあるあるな奴やんけ…</b>」と思ったのでMATLAB芸人として我慢できず、反射的に書きました。

タイトルが思いっきりパクリなのですが、先行記事をリスペクトしすぎる上での判断なので勘弁頂きたい。だって本当に素晴らしいタイトルなんですもの😇

MATLAB、開発チームの心遣いからか大変便利な演算子やコマンドが多く素晴らしいと思う一方で、<b>あまりにも情報圧縮しすぎてググりにくい</b>という弊害があると思っています。（本文に上げている`[~, x]`とかどう調べろっつーねん）
なので初心者が:thinking:となる→ググっても見つからず時間が溶ける😇 という事案がそこそこ発生します。私もいっぱい溶かしてきたので、皆さんがそうならないことを願ってこの記事を書きます。

なお本記事の副読本としてMathworks公式ドキュメント[MATLAB の演算子と特殊文字](https://jp.mathworks.com/help/matlab/matlab_prog/matlab-operators-and-special-characters.html)を一通り読むことを強く勧めます。
（そもそも最初からこれちゃんと読んでおけば:thinking:となるのを回避できるのですが…私は必要に応じてしか読んでないから😇となっている）

# \
## is 何
逆行列。[MATLAB Tシャツ](https://blogs.mathworks.com/cleve/2013/08/19/backslash/)でもおなじみ、MATLABで最もセクシーな演算子。
MATLABの言語設定を日本語にしていると`¥`になってしまう点が少し残念。

```matlab
% 行列を作成
A = [1 2;
    1 3];

%単位行列
B = [1 0;
    0 1];

%Aの逆行列を計算
C = A \ B
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/673e3ad7-047c-ccd6-68a0-dfc563dffa59.png)
ちなみに逆行列は、`inv(A)`とか`A^-1`でも求められます。`\`を使うと通ぶれるので積極的に使いましょう。

なお`\`は`inv(A)`と比べ<b>計算時間が早い＆残差誤差も少ない</b>という優れた特徴があります、詳細は下記。教えてくれた@sasayaさんありがとう！
https://jp.mathworks.com/help/matlab/ref/inv.html

これはもう`\`を使うしかないですね。

# .*
## is 何
各要素ごとの掛け算。大変便利なので覚えましょう。
ドット`.`と演算子を組み合わせることで「各要素ごとの＊＊」になります。
個人的によく使うのは`.*` `./` `.^` あたり。

```matlab
A = [1 2 3];
B = [10 20 30];

C = A .* B
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/6bd084cb-bec8-7922-e881-147a90270956.png)


# (:, n)
## is 何
n列目の要素全て。逆に`(n, :)`だとn行目の要素全てになる。

```matlab
A = [1 2;
    3 4];

n = 2;

B = A(:, n)
C = A(n, :)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/8ce03da2-198b-0761-dca5-43670f043755.png)

さらなる発展形として、`(:, :, n)`というのもある。
画像データのRGBのいずれか１つを抽出する際に有効。

```matlab
img = imread('peppers.png');

img_Red = img(:, :, 1);
img_Green = img(:, :, 2);
img_Blue = img(:, :, 3);

subplot(2,2,1);
imshow(img);

subplot(2,2,2);
imshow(img_Red);

subplot(2,2,3);
imshow(img_Green);

subplot(2,2,4);
imshow(img_Blue);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/b0b5de3d-c7f7-84d8-6a23-8415366f745d.png)



# subplot(211)
## is 何
`subplot(2,1,1)`の省略形。
つまり、上記のコードは下記でも同じように動くのである。著しく可読性を下げるので人に見せるコードでは使わないようにしましょう、してくれ頼む。

```matlab
img = imread('peppers.png');

img_Red = img(:, :, 1);
img_Green = img(:, :, 2);
img_Blue = img(:, :, 3);

subplot(221);
imshow(img);

subplot(222);
imshow(img_Red);

subplot(223);
imshow(img_Green);

subplot(224);
imshow(img_Blue);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/b0b5de3d-c7f7-84d8-6a23-8415366f745d.png)

# ...
## is 何
長ったらしいコードの改行。

```matlab
options=optimoptions('ga','InitialPopulationMatrix', ...
                        initpop,'Display','iter','OutputFcn',@myfun);
``` 
ちなみに、複数行の行列を宣言する場合においてセミコロン`;`の後にこの改行を書かなくてもOKです。
(追記)改行さえしてあれば`;`すらも不要です。可読性的にどうなの、というのはさておき。

```matlab
% これでももちろんＯＫだけど
A = [1 2 3; ...
    4 5 6];

% これでもＯＫ
A = [1 2 3; 
    4 5 6];

% これでもＯＫ
A = [1 2 3 
    4 5 6];
```

#'
## is 何
[複素共役転置](https://jp.mathworks.com/help/matlab/ref/ctranspose.html)。
ただの転置は`.'`だが、転置する対象が実数の場合は`'`と`.'`のどちらを使っても結果は同じなので`'`を使う人も多い（と勝手に思っている）。しかしながら将来におけるバグの原因となるので、使い分けたほうがベターではある。

```matlab
% これと
A = [1:3]';

% これは結果が同じ
A = [1:3].';
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/5c167322-5002-0416-ec21-9d1a7f43b94c.png)

複素数の場合は言わずもがら、結果が変わってくるのでご注意。

```matlab
A = [1+i 1-i];

B = A.'
C = A'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/206eb10c-47ac-cfb4-a57a-7b3acf9e3470.png)

# 1i
## is 何
複素数の作成。[【MATLAB】行列を与えると随伴行列を返す関数を作って...](https://qiita.com/takumi_ueda/items/515e73fb69952e276ae0#comment-8531a16cf18471de02aa)の@eigsさんのコメントから拝借。

複素数は下記３つのいずれのパターンでも書ける、試しに足してみよう。

```matlab
A = 1i;
B = i;
C = sqrt(-1);

D = A + B + C
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/c7f1755f-6f93-b701-b114-52f2f2a3cec1.png)

`i`が複素数として使えるのは使用以前に内容を定義していない場合のみで、定義していた場合は下記のようになる。

```matlab
i = 1;

A = 1i;
B = i;
C = sqrt(-1);

D = A + B + C
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/6e2ee270-e59f-6106-cfcd-3a0a08f5f579.png)

`1i`や`2i`のように使うのが一番よさそうですね。試してみたら`0.1i`もいけました。
`sqrt(2)i`は流石にNG、`sqrt(2)*1i`ならＯＫ。

# e3
## is 何
10の累乗。`e3`なら10の3乗ということ。何気に便利。`e+3`や`e+03`といった表現も可能です。
実際には`e`の前に何かしらの数字が必要になります。

```matlab
A = 2.5e3
B = 2.5e-3
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/ba25ec1a-df1b-bec8-5a50-28940f377891.png)

複素数`1i`との組み合わせもいけるのかしら？と思ったが`1ie3`や`1i*e3`はNG。下記ならOK。

```matlab
A = 1i * 1e3
B = 1e3 * 1i
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/eeba3c7f-54eb-31cb-6df0-3867fc7eda44.png)




# @(x)
## is 何
無名関数の関数ハンドル。
そもそも無名関数って何じゃい、って方は丸田先生のSlideShare[「関数型プログラミング入門 for Matlab ユーザー」](https://www.slideshare.net/IchiroMaruta/for-matlab)を読みましょう、神。

```matlab
f = @(x) sin(x) + sin(3*x);
fplot(f);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/e1b79ab4-27ac-8f27-2bcd-d3adeaabb794.png)

ちなみに`fplot`は関数から直接グラフをplotするための関数で、これも上記SlideShare内で紹介されています。
念のため`fplot`を使わない場合は下記。plot結果がスムーズでなくなる点もSlideShareにて言及されてます、神。

```matlab
f = @(x) sin(x) + sin(3*x);
X = [-5 : 0.1 : 5];
Y = f(X);
plot(X,Y);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/b6a3ffaf-1632-663e-0423-8649be927204.png)


# [~, x]
## is 何
関数の戻り値のうち不要なものを`~`で捨てる。高速化のためのテクニック。

```matlab
A = [20 30 10 0];

% A行列のうちで小→大に並び替える際の順番だけを知りたい
[~, idx] = sort(A)

% idxを使ってA行列の2番目に大きい数字を取り出す
A( idx(2) )
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/b398c93a-2877-51de-4e37-2d7f62c2f42a.png)

# (:)
## is 何
行列の書き下し。

```matlab
A = [1 2;
    3 4];

B = A(:)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/20eba087-7113-7922-605a-0b5507d1352e.png)

これどこで使うんだろう？と思ってたが、[表記ゆれ対策を力業で実装](https://qiita.com/aoimidori/items/9678631a966a4a6abc40)にて<b>行列の全要素加算</b>に使っていてなるほど！と唸りました。

```matlab
A = [1 2;
    3 4];

B = sum( A(:) )
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/cfa2cfb8-92a9-09b8-942e-9f2abb34cd86.png)

これって組み込み関数にないのか？:thinking:　と思ったら2018bから`sum(A,'all')`で可能になったとのこと。
https://jp.mathworks.com/help/matlab/ref/sum.html#mw_e734edf5-eab5-4791-be5c-355b3db91052

うーん、可読性は`sum(A,'all')`に軍配が、クールさは`sum(A(:))`に軍配があるかな。

# []
## is 何
空の配列を定義。
何に使うかというと、`for`ループ内でデータを横に横に（もしく縦に縦に）つなげる際の初期化に使うと便利。

```matlab
A = [];
for i = 1:3
    A = [A i];
end
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/7668a31c-a39c-c7d5-d63c-9b9e8a58ef66.png)

ただしこのやり方は処理速度を劣化させる。処理速度を速めるには配列サイズをあらかじめ確定させる必要がある…が、面倒なので急いでいる時は`[]`を使ってしまう悪い癖。

```
A = zeros(1, 3);
for i = 1:3
    A(i) = i;
end
```
`[]`を使った場合は実行時間0.07秒、配列サイズ確定の場合は実行時間0.02秒でした。

# gcf
Get Current Figureの略。現在アクティブになっているfigureのハンドルを取得する。
同様に`gca`はGet Current Axesの略なのでセットで覚えましょう。

# clc
Clear Command Windowの略。コマンドウィンドウを一旦消す。
clc (コマンドウィンドウ消す)
clear all (ワークスペース消す)
close all (Figure閉じる)
をワンセットで使っている人も多いと思う。

小ネタとして、最近のMATLABだとお気に入りコマンドを作成登録できる。
上記３つのセットを登録しておくと楽ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/3da83cb7-7e6e-5d71-f269-39778598b79b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/0081b95e-2307-a0e9-d286-d45df50b4494.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302506/8bbe5abf-bdef-a81b-5313-d52b7f2e8c7c.png)

# まとめ
今後:thinking:→😇となるようなことがあれば追記していきます。
また他にも:thinking:→😇となった経験をお持ちの方はコメントや編集リクエストにてお寄せ下さい。