はじめに

MATLABでプログラムを開発する上で、フロー制御の理解は欠かせません。処理の分岐や繰り返し、プログラムの終了方法を的確に使い分けることで、効率の良いコードを書くことができます。本記事では、以下のポイントを中心に、MATLABでのフロー制御について解説します。

  1. 条件付き制御 — if、else、switch
  2. ループ制御 — for、while、continue、break
  3. プログラムの終了 — return
  4. ベクトル化
  5. 事前割り当て

この記事を参考にしながら、MATLAB独自のフロー制御の書き方や、パフォーマンス向上を意識したコーディング手法を学んでいきましょう。

キーワード再掲:MATLAB, フロー制御, if, else, switch, for, while, continue, break, return, ベクトル化, 事前割り当て

1. 条件付き制御 — if、else、switch

1.1 if ~ else ~ end

MATLABで条件分岐を行う場合、典型的な構文は以下のとおりです。

x = 5;

if x > 0
    disp('xは正の数です');
elseif x < 0
    disp('xは負の数です');
else
    disp('xはゼロです');
end

if 条件: 条件式が true のときの処理

  • elseif 条件: 上記が false で、こちらが true のときの処理
  • else: 上記すべてが false のときの処理

図1.条件分岐’if’の使用例

1.2 switch ~ case ~ otherwise

複数の条件分岐がある場合、switch 構文が見やすいケースがあります。以下は例です。

color = 'blue';

switch color
    case 'red'
        disp('色は赤です');
    case 'blue'
        disp('色は青です');
    case 'green'
        disp('色は緑です');
    otherwise
        disp('未知の色です');
end

switch を使うと、特定の値に応じた処理を整理しやすくなります。

図2.条件分岐’switch’の使用例

2. ループ制御 — for、while、continue、break

2.1 for ループ

連続した範囲のインデックスや配列要素に対して処理を繰り返す場合、for ループが便利です。

for i = 1:5
    disp(['ループカウンタ i = ' num2str(i)]);
end

2.2 while ループ

条件が満たされるまで繰り返したい場合は while を使います。

i = 0;
while i < 5
    disp(['i = ' num2str(i)]);
    i = i + 1;
end

2.3 continue と break

  • continue: ループ内の処理をスキップして、次の反復へ移行
  • break: ループそのものを強制終了
for i = 1:10
    if mod(i,2) == 0
        continue;  % 偶数のときはスキップ
    end
    if i > 7
        break;     % iが7より大きい場合はループ終了
    end
    disp(i);
end

図3.ループ制御の使用例

3. プログラムの終了 — return

MATLABの関数内で、ある条件が成立した時点で処理を終わらせたい場合は return を使います。return に到達すると、そこで関数を即座に抜けます。

function myFunction(x)
    if x < 0
        disp('xは負の数なので処理を終了します。');
        return; % ここで関数を終了
    end
    % xが非負の場合の後続処理
    disp('xは負の数ではありません。');
end

スクリプトファイルでは return に大きな意味はありませんが、関数内では重要なフロー制御手段となります。

4. ベクトル化

MATLABは「行列(配列)」を効率よく扱うために設計されています。ループを多用せずに、配列演算で一括処理する「ベクトル化」は、コードの簡潔化や高速化に有効です。

4.1 例:要素ごとの演算

ループで書く代わりに、ベクトル化を使うと次のように一行で書けます。
forループで要素ごとに計算するより、ベクトルで計算した方が早く処理が終わります。

% ループ版の計算
x = 1:0.01:10000;           % ベクトルxを定義
y = zeros(size(x));         % 結果を格納するyをxと同じサイズで初期化
tic;                        % 実行時間計測の開始
for i = 1:length(x)         % ループで計算
    y(i) = x(i)^5 - x(i)^3 + 2*x(i) - 1; % 各要素について計算
end
loop_time = toc;            % 実行時間を記録

% ベクトル化版の計算
x = 1:0.01:10000;           % ベクトルxを再定義
tic;                        % 実行時間計測の開始
y = x.^5 - x.^3 + 2.*x - 1; % ベクトル化で計算
vectorized_time = toc;      % 実行時間を記録

% 結果をコマンドウィンドウに表示
disp('計算時間の比較:');
disp(['ループ版の実行時間: ', num2str(loop_time), ' 秒']); % ループ版の実行時間を表示
disp(['ベクトル化版の実行時間: ', num2str(vectorized_time), ' 秒']); % ベクトル化版の実行時間を表示

図4.ベクトル化による処理の高速化

表1.行列演算・要素ごとの演算一覧表

演算の種類行列演算要素ごとの演算説明
加算A + B同じ行列または要素を加算
減算A - B同じ行列または要素を減算
乗算A * BA .* B行列積または要素ごとの積
除算A / B または A \ BA ./ B または A .\ B行列除算または要素ごとの除算
累乗A^nA.^n行列の累乗または要素ごとの累乗
転置A'A.'共役転置または非共役転置
ゼロ行列作成zeros(m, n)同じm×nm \times nm×n のゼロ行列を作成
単位行列作成eye(n)N/An×nn \times nn×n の単位行列を作成
要素の和sum(A)同じ各列または行方向の合計値を計算
最大値max(A)同じ行列内の最大値を返す

5. 事前割り当て

MATLABで配列を拡張しながら要素を追加していくと、内部でメモリ再割り当てが何度も起こり、実行速度が低下する原因となります。そこで、あらかじめ目的のサイズを確保しておく**「事前割り当て」**が推奨されます。

5.1 例:ゼロ行列で初期化

サイズが変わる配列に代入すると、再割り当てによってループが遅くなることが多いです。

% 配列サイズを変化させる
n_values = [100, 1000, 5000, 10000, 20000, 50000];  % 配列サイズの候補
time_preallocated = zeros(size(n_values));          % 事前割り当てありの実行時間
time_not_preallocated = zeros(size(n_values));      % 事前割り当てなしの実行時間

% 各配列サイズで計測
for idx = 1:length(n_values)
    n = n_values(idx);                              % 現在の配列サイズ

    % 事前割り当てあり
    A = zeros(n, 1);                                % 配列を事前に割り当て
    tic;                                            % 実行時間計測開始
    for i = 1:n
        A(i) = i * 2;                               % メモリ再確保なしで代入
    end
    time_preallocated(idx) = toc;                   % 実行時間を記録

    % 事前割り当てなし
    A = [];                                         % 配列を初期化
    tic;                                            % 実行時間計測開始
    for i = 1:n
        A(i) = i * 2;                               % 配列サイズを都度拡張して代入
    end
    time_not_preallocated(idx) = toc;               % 実行時間を記録
end

% グラフをプロット
figure;
plot(n_values, time_preallocated, '-o', 'LineWidth', 1.5); % 事前割り当てありの実行時間
hold on;                                            % グラフ保持
plot(n_values, time_not_preallocated, '-x', 'LineWidth', 1.5); % 事前割り当てなしの実行時間
hold off;                                           % グラフ保持解除

% グラフの装飾
title('事前割り当てあり/なしの実行時間比較');       % グラフタイトル
xlabel('配列サイズ n');                             % x軸ラベル
ylabel('処理時間 (秒)');                            % y軸ラベル
legend('事前割り当てあり', '事前割り当てなし', 'Location', 'northwest'); % 凡例を追加
grid on;   

図5.事前割当の有無よる処理速度の違い

まとめ

本記事では、MATLABにおけるフロー制御の重要ポイントを以下の5つに分けて解説しました。

  1. 条件付き制御(if, else, switch)
  2. ループ制御(for, while, continue, break)
  3. プログラムの終了(return)
  4. ベクトル化
  5. 事前割り当て

効率的なコード作成には、単純な分岐や繰り返しを理解するだけでなく、MATLABならではのベクトル化や事前割り当てのメリットを活用することが重要です。

さらなる学習リソース

  • MathWorks公式ドキュメント(日本語)
    フロー制御ステートメント
  • MATLAB Answers (Q&Aフォーラム)
    具体的なフロー制御の実装例や最適化についての議論が多数あり
  • YouTube MathWorks公式チャンネル
    動画でMATLABのフロー制御の基本を学べるチュートリアルが充実

キーワード再掲:MATLAB, フロー制御, if, else, switch, for, while, continue, break, return, ベクトル化, 事前割り当て