[PHP] 関数電卓なみの計算をしよう(5) for文

関数電卓で、数表作成ができます。似たことをphpスクリプトで計算してみましょう。

関数電卓とは

関数電卓すごすぎて、関数電卓なみとか言ってられないわ

観覧車の回転角度と位置

15分で1周する、半径50mの観覧車に乗客が乗った。


観覧車の中心から両側37.15mの場所にある通路の真上に最初に来るのは乗ってから何分後か?
乗客が観覧車の隣にある高さ90.45mのビルと同じ高さに来るのは乗ってから何分後か?

https://edu.casio.jp/cal/cal19/

この例題の関数電卓の使い方の注目ポイントは2つです。

1つ目は、ユーザ定義の関数f(x)、g(x)を設定する。f(x) = 50 - 50cos(360x/15)、g(x) = 50sin(360x/15)

2つ目は、xの開始値=0、終了値=15、ステップ値=1を設定して、xについて0〜15まで実行して、表を作ります。

今回作るphpスクリプトでは、ユーザー定義関数を作らず、変数$f や 変数$g に計算結果を代入することにします。

関数電卓は、sin関数、cos関数に渡す角度の単位を度数法または弧度法を切り替えることができ、例題では度数法で計算しています。

PHPのsin関数、cos関数に渡す引数は、ラジアンなので、xからラジアンを計算します。

<?php
$x = 0;
$a = 2 * M_PI * $x / 15;
Code language: PHP (php)

次に、高さ f(x) = 50 - 50cos(360x/15) を計算します。

// つづき
$f = 50 - 50 * cos($a);Code language: PHP (php)

つづいて、水平方向の位置 g(x) = 50sin(360x/15)を計算します。

// つづき
$g = 50 * sin($a);Code language: PHP (php)

$x、$f、$gを表示します。sprintf関数は、後で説明します。

// つづき
echo sprintf("%2d  %7.3f  %7.3f\n", $x, $f, $g);
Code language: PHP (php)

まとめると

<?php
$x = 0;
$a = 2 * M_PI * $x / 15;
$f = 50 - 50 * cos($a);
$g = 50 * sin($a);
echo sprintf("%2d  %7.3f  %7.3f\n", $x, $f, $g);Code language: PHP (php)

実行すると、

 0    0.000    0.000Code language: plaintext (plaintext)

$x を 1にして、実行すると、

<?php
$x = 1;
// 以下、変更なしCode language: PHP (php)
 1    4.323   20.337Code language: plaintext (plaintext)

$x を2、3、4、5と変更して、実行すると、

 2   16.543   37.157Code language: plaintext (plaintext)
 3   34.549   47.553Code language: plaintext (plaintext)
 4   55.226   49.726Code language: plaintext (plaintext)
 5   75.000   43.301Code language: plaintext (plaintext)

手作業で$xの値を0、1、2、3、4、5と変更しました。プログラムでこれと同じことをする方法が、for文です。for文も、後ほど説明します。

<?php
for ($x = 0; $x <= 15; $x += 1) {
    $a = 2 * M_PI * $x / 15;
    $f = 50 - 50 * cos($a);
    $g = 50 * sin($a);
    echo sprintf("%2d  %7.3f  %7.3f\n", $x, $f, $g);
}Code language: PHP (php)

実行すると、

 0    0.000    0.000
 1    4.323   20.337
 2   16.543   37.157
 3   34.549   47.553
 4   55.226   49.726
 5   75.000   43.301
 6   90.451   29.389
 7   98.907   10.396
 8   98.907  -10.396
 9   90.451  -29.389
10   75.000  -43.301
11   55.226  -49.726
12   34.549  -47.553
13   16.543  -37.157
14    4.323  -20.337
15    0.000   -0.000Code language: plaintext (plaintext)

観覧車の中心から両側37.15mの場所にある通路の真上に最初に来るのは乗ってから何分後か?

これは、3列目の$gを見て、2分後、13分後とわかります。

乗客が観覧車の隣にある高さ90.45mのビルと同じ高さに来るのは乗ってから何分後か?

これは、2列目の$fを見て、6分後、7分後とわかります。

sprintf関数

%だらけで呪文みたいだよ...

sprintf関数は、string print formatの略で、書式つき文字列表示関数です。

ワープロの「書式」とは、右寄せ、左寄せ、中央寄せやフォントの色やサイズのことです。

sprintf関数の「書式」とは、主に、右寄せ、左寄せ、表示する桁数、浮動小数点として表示するのか、10進数として表示するのか、16進数として表示するのか、などを指定します。

さきほど使ったsprintf関数です。

echo sprintf("%2d  %7.3f  %7.3f\n", $x, $f, $g);
Code language: PHP (php)

"%2d %7.3f %7.3f\n"が書式、$x、$f、$g が表示する変数です。sprintf関数は、引数の個数が決まっていない可変長引数の関数です。

書式内の %〜d や %〜f を書式指定子といいます。

1つ目の書式指定子が、1つ目の表示変数の表示方法を指定します。つづけて、2つ目の書式指定子が、2つ目の表示変数の表示方法を指定します。

さきほどの書式指定子と表示変数の対応は次のようになります。

書式指定子表示する変数
%2d$x
%7.3f$f
%7.3f$f

%2dは、2 は 2桁、dは10進数の整数として表示します。0〜9は、左側にスペースをつけて、2桁表示します。

dは、decimal、10進数という意味ね

%7.3fは、最初の7が7桁、.3 が小数点以下を3桁表示、fは浮動小数点数として表示します。小数点より上が3桁(マイナス符号を含みます)、小数点自体で1桁、小数点以下を3桁、で表示します。桁数が足りないときは、左にスペースをつけます。

fは、float、浮動小数点数という意味ね

for文

関数電卓では、xの値を開始値:0、終了値:15、ステップ値:1と設定することで、xの値を1、2、3、4、と変化させながら、x、f(x)、g(x)の値を表示していました。

「xの値を開始値:0、終了値:15、ステップ値:1」のような繰り返し処理では、xをループカウンタと呼びます。for文で繰り返すことをループカウンタで回す、と表現することがあります。

for文は、次のような構成になっています。for文のカッコ内()は、セミコロン;2個で区切られています。

for (開始値の設定; 終了値の設定; ステップ値の設定) {
    処理
}
Code language: plaintext (plaintext)

「xの値を開始値:0、終了値:15、ステップ値:1」の場合、次のように書きます。

<?php
for ($x = 0; $x <= 15; $x += 1) {
    処理
}
Code language: PHP (php)

ループカウンタ

(1) 開始値の設定

上の例では、$x がループカウンタです。

多くの場合、ループカウンタに0を代入します。

(2) 終了値の設定、繰り返し条件

15(を含む)まで回すので、$x <= 15 です。0〜15まで16回繰り返します。

($xが 0 から 14まで、全部で15回繰り返すときは、$x < 15 と書きます。)

$x <= 15がTrueの間は繰り返すんだね。

「終了値の設定」というよりは「繰り返し条件」のほうが正確かしら

(3) ステップ値の設定

ループカウンタの値をステップ値だけ増やします。

$x += 1 は、$x = $x + 1 と同じ意味です。ある変数の値に足して、その変数に代入する計算は、とてもよく使うので、このための演算子 += があります。

さらに $x += 1 は、$x++++$xとも書くことができるのですが、++演算子(インクリメント)、--演算子(デクリメント)は、使い方が難しいので、$x += 1 を使ってください。

++演算子や--演算子は、Swift3ではなくなってしまったわね

波カッコとインデント

(4) 波カッコ

波カッコ内に、繰り返し処理を書きます。

この繰り返し処理が1行の場合、波カッコを省略できるのですが、その場合でも、波カッコを省略しないでください。

// よくない例:波カッコを省略している
for ($x = 0; $x <= 15; $x += 1)
    echo f($x);

// よい例:波カッコを省略できる場合でも省略しない
for ($x = 0; $x <= 15; $x += 1) {
    echo f($x);
}Code language: plaintext (plaintext)

(5) 波カッコの位置

開きカッコは for の行末に書いてください。

// PHPの主流の例
for ($x = 0; $x <= 15; $x += 1) {
    処理
}

// PHPではほとんど使われない例
for ($x = 0; $x <= 15; $x += 1)
{
    処理
}Code language: plaintext (plaintext)

(6) 繰り返し処理

波カッコ内の処理は、スペース4個か水平タブで、インデントします。インデントしなくてもPHPの文法としては正しいのですが、必ずインデントするようにしてください。

最近のテキストエディターは自動でインデントしてくれるわ

// 悪い例:インデントしていない
for ($x = 0; $x <= 15; $x += 1) {
echo f($x);
echo "\n";
}

// よい例:インデントしている
for ($x = 0; $x <= 15; $x += 1) {
    echo f($x);
    echo "\n";
}Code language: plaintext (plaintext)

PHPのfor文は、C言語由来のfor文です。古い文法であり、バグの原因になりやすい欠点があります。

欠点とは、ループカウンタの値を、繰り返し処理のなかで変更できてしまうことです。わざとそうすることもありますが、通常はしないでください。

// 繰り返しが1回だけ
for ($x = 0; $x <= 15; $x += 1) {
    $x = 100;
}

// 無限ループ
for ($x = 0; $x <= 15; $x += 1) {
    $x = 0;
}
Code language: PHP (php)

1行1コマのスゴロク

おおざっぱに言うと、phpスクリプトは、1行1コマのスゴロクに似ています。

お寿司?

それは助六

次のスクリプトを1行づつ実行していく様子を見ましょう。

説明の都合で、繰り返し回数は2回、$x <= 1; にしました。

<?php
for ($x = 0; $x <= 1; $x += 1) {
    $a = 2 * M_PI * $x / 15;
    $f = 50 - 50 * cos($a);
    $g = 50 * sin($a);
    echo sprintf("%2d  %7.3f  %7.3f\n", $x, $f, $g);
}
Code language: PHP (php)

1行目からスタートします。

1: <?phpCode language: PHP (php)

PHPの開始タグです。
次の行に進みます。

2行目 開始値の設定

2: for ($x = 0; Code language: PHP (php)

$xに0を代入します。
繰り返し条件に進みます。

2行目 繰り返し条件

2: $x <= 1;Code language: PHP (php)

$xは0なので、$x <= 1はTrueです。for文の繰り返し処理の最初の行、3行目へ進みます。

3行目〜6行目

3:    $a = 2 * M_PI * $x / 15;
4:    $f = 50 - 50 * cos($a);
5:    $g = 50 * sin($a);
6:    echo sprintf("%2d  %7.3f  %7.3f\n", $x, $f, $g);Code language: PHP (php)

3行目〜6行目を処理します。6行目が繰り返し処理の終わりの行です。
2行目 ステップ値の設定へ進みます。

2行目 ステップ値の設定

2: $x += 1) {Code language: PHP (php)

$xは0なので、$x += 1 で、1を代入します。
2行目 繰り返し条件へ進みます。

2行目 繰り返し条件

2: $x <= 1;Code language: PHP (php)

$xは1なので、$x <= 1はTrueです。for文の繰り返し処理の最初の行、3行目へ進みます。

3行目〜6行目

3:    $a = 2 * M_PI * $x / 15;
4:    $f = 50 - 50 * cos($a);
5:    $g = 50 * sin($a);
6:    echo sprintf("%2d  %7.3f  %7.3f\n", $x, $f, $g);Code language: PHP (php)

3行目〜6行目を処理します。6行目が繰り返し処理の終わりの行です。
2行目 ステップ値の設定へ進みます。

2行目 ステップ値の設定

2: $x += 1) {Code language: PHP (php)

$xは1なので、$x += 1 で、2を代入します。
2行目 繰り返し条件へ進みます。

2行目 繰り返し条件

2: $x <= 1;Code language: PHP (php)

$xは2なので、$x <= 1はFalseです。
for文の閉じカッコの次の行、8行目へ進みます。

8行目はないので、プログラム終了です。

わかったような、わからないような

読むだけでなく、写経してね

タイトルとURLをコピーしました