Main Content

フロー制御

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

条件付きステートメントでは、ランタイムに実行するコードのブロックを選択できます。最もシンプルな条件付きステートメントは、if ステートメントです。以下に例を示します。

% Generate a random number
a = randi(100, 1);

% If it is even, divide by 2
if rem(a, 2) == 0
    disp('a is even')
    b = a/2;
end

if では、オプションのキーワード elseif または else を使用して、代替の選択肢を含めることができます。以下に例を示します。

a = randi(100, 1);

if a < 30
    disp('small')
elseif a < 80
    disp('medium')
else
    disp('large')
end

または、一連の既知の値を使用して等価性をテストする場合は、switch ステートメントを使用します。以下に例を示します。

[dayNum, dayString] = weekday(date, 'long', 'en_US');

switch dayString
   case 'Monday'
      disp('Start of the work week')
   case 'Tuesday'
      disp('Day 2')
   case 'Wednesday'
      disp('Day 3')
   case 'Thursday'
      disp('Day 4')
   case 'Friday'
      disp('Last day of the work week')
   otherwise
      disp('Weekend!')
end

ifswitch のいずれの場合も、真である最初の条件まで対応するコードが実行されて、コード ブロックが終了されます。各条件付きステートメントでは、end キーワードが必要です。

一般的に、考えられる既知の離散値が多数ある場合は、if ステートメントよりも switch ステートメントの方が読みやすくなります。ただし、switch の値と case の値の間で非等価性をテストすることはできません。たとえば、switch で次のような条件を使用することはできません。

yourNumber = input('Enter a number: ');

if yourNumber < 0
    disp('Negative')
elseif yourNumber > 0
    disp('Positive')
else
    disp('Zero')
end

条件付きステートメントにおける配列の比較

関係演算子と if ステートメントが行列にどのように機能するかを理解することは重要です。2 つの変数間の等価性をチェックする場合、次のようにします。

if A == B, ...

これは正しい MATLAB® のコードで、AB がスカラーであるときに予想されることを実行します。しかし、AB が行列の場合、A == B はそれらが "等しいかどうか" をテストせずに、それらの "どこが等しいか" をテストします。結果は、要素ごとの等価性を表わす 0 と 1 からなる行列になります。

A = magic(4);
B = A;
B(1,1) = 0;

A == B

ans =

  4×4 logical array

   0   1   1   1
   1   1   1   1
   1   1   1   1
   1   1   1   1

2 つの変数間の等価性をチェックする適切な方法は、関数 isequal を使うことです。

if isequal(A, B), ...

isequal は、関数 if による結果の表現として、行列ではなく "スカラー" logical 値 1 (trueを表す) または 0 (false) を出力します。上記の行列 AB を使って以下を得ます。

isequal(A,B)

ans =

  logical

   0

次に、このことを強調する他の例を示します。AB がスカラーである場合、次のプログラムは予想通りの結果になります。列を交換した魔方陣を含む行列のほとんどの組に対して、行列の条件 A > BA < B、または A == B"どの" 要素に対しても真ではないため、else 句が実行されます。

if A > B
   'greater'
elseif A < B
   'less'
elseif A == B
   'equal'
else
   error('Unexpected situation')
end

次の関数は、if と共に使って、行列の比較結果をスカラー条件にするのに使うことができます。

isequal
isempty
all
any

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

この節では、プログラムのループ制御を与える以下の MATLAB 関数を述べます。

for

for ループは、前もって定義した固定回数だけステートメント群を繰り返し実行します。対応する end でステートメント群を区別します。

for n = 3:32
   r(n) = rank(magic(n));
end
r

ループ内のステートメントの最後のセミコロンは、繰り返し表示されないようにして、最終結果を表示するためループの後に r を使います。

読みやすくするため、特に入れ子状態のときには、ループにインデントを適用することは良い考えです。

for i = 1:m
   for j = 1:n
      H(i,j) = 1/(i+j);
   end
end

while

while ループは、回数を定義しないで、繰り返し回数を論理条件によりコントロールするときに使います。対応する end でステートメント群を区別します。

whileifelseend を使ったプログラムを示します。これは、多項式のゼロを見つけるために区間 2 分割を使います。

a = 0; fa = -Inf;
b = 3; fb = Inf;
while b-a > eps*b
   x = (a+b)/2;
   fx = x^3-2*x-5;
   if sign(fx) == sign(fa)
      a = x; fa = fx;
   else
      b = x; fb = fx;
   end
end
x

結果は、多項式 x 3 – 2 x – 5 の根になります。つまり、次のようになります。

x =
   2.09455148154233

if ステートメントの節で議論した行列比較に関する注意は、while ステートメントにも適用されます。

continue

ステートメント continue は、ループの本体の中で、for、または、while のループの中で、あるステートメントをスキップして、次の反復をコントロールします。入れ子のループ内の continue ステートメントに対して同じことが当てはまります。つまり、continue ステートメントが遭遇したループの初めで実行が続きます。

次の例は、continue ループを使って、ファイル magic.m の中の空白行とコメント行をスキップしたコードのラインをカウントするものです。continue ステートメントを使って、空白行やコメント行に出会うとカウントしないで、magic.m の中の次のラインに進みます。

fid = fopen('magic.m','r');
count = 0;
while ~feof(fid)
    line = fgetl(fid);
    if isempty(line) || strncmp(line,'%',1) || ~ischar(line)
        continue
    end
    count = count + 1;
end
fprintf('%d lines\n',count);
fclose(fid);

break

break ステートメントは、for または while ループから抜け出すためのものです。入れ子になったループでは、break は最下部のループのみから退出します。

前の節の例を改良したものを以下に示します。break の使用はなぜ良い考えなのでしょうか?

a = 0; fa = -Inf;
b = 3; fb = Inf;
while b-a > eps*b
   x = (a+b)/2;
   fx = x^3-2*x-5;
   if fx == 0
      break
   elseif sign(fx) == sign(fa)
      a = x; fa = fx;
   else
      b = x; fb = fx;
   end
end
x

プログラムの終了 — return

この節では、プログラムを最後まで実行せず途中で終了させる MATLAB 関数 return について述べます。

出力

return はコマンドの現在のシーケンスを終了し、起動関数またはキーボードに制御を戻します。return は、keyboard モードの終了にも使用されます。呼ばれた関数は通常その機能を終了すると、それを起動した関数に制御を移します。呼ばれた関数の中に return を挿入することで強制的に早く終了し起動した関数に制御を移すことができます。

ベクトル化

MATLAB をスピードアップする 1 つの方法は、M ファイルのアルゴリズムをベクトル化することです。他のプログラミング言語が for または DO ループを使う部分で、MATLAB ではベクトルまたは行列演算を使うことができます。次のコードは、簡単な例として、対数表を作成するものです。

x = 0.01;
y = log10(x);
for k = 1:999
  x(k+1) = x(k) + 0.01;
  y(k+1) = log10(x(k+1));
end

同じコードをベクトル化すると、次のようになります。

x = .01:.01:10;
y = log10(x);

さらに複雑なコードに対しては、ベクトル化の効果が常に顕著とは限りません。

事前割り当て

コードの一部をベクトル化することができない場合、出力結果をストアする ベクトルまたは配列を前もって設定しておくことによって for ループをスピードアップできます。たとえば、次のコードは、for ループで作成されるベクトルを前もって作成するために関数 zeros を使うものです。これにより、for ループの実行はかなり速くなります。

r = zeros(32,1);
for n = 1:32
    r(n) = rank(magic(n));
end

前の例の中で前もってスペースを設定しないと、MATLAB インタープリターは、ループに関する 1 回の実行で、1 要素ずつ r ベクトルを拡大します。ベクトルの領域を前もって確保することは、この手順を省略させ、より高速の実行になります。