高校数学をプログラミングで解く(数学I編)「1-1 関数とグラフ」
はじめに
今回は、数学Iで学ぶ「関数とグラフ」について、1次関数と2次関数のグラフを描くプログラムや2次関数の最小値を求めるプログラムなどを作成します。
1次関数のグラフを描く
まず、1次関数
$$
y=\frac{1}{2}x+1
$$
のグラフを描きます。
1次関数をプログラムの関数として準備
1次関数をプログラムの関数として準備します。関数化については記事『高校数学をプログラミングで解く(準備編)「3-2 関数の作成」』で解説しています。
// 一次関数の関数
float linearfunction(
float x
){
return 1.0/2.0 * x + 1.0;
}
ソースコード1 1次関数$${y=\frac{1}{2}x+1}$$の関数
1次関数のグラフを描く
記事『高校数学をプログラミングで解く(数学I編)「1-0-1 グラフを描くための準備(その1)」』及び『高校数学をプログラミングで解く(数学I編)「1-0-2 グラフを描くための準備(その2)」』で説明したグラフの描画方法を利用して、1次関数のグラフを描いてみます。
スケッチ「drawLinearFunction」を準備し、その「drawLinearFunction」フォルダに「setAxes.pde」ファイルをコピーします。このとき、スケッチ「drawLinearFunction」の開発環境ウィンドウは図1のように、タブ欄に「setAxes」タブが追加された形になります。
これにより、「setAxes.pde」ファイルに記述したsetAxes関数を利用することができるようになります。
では、1次関数を描くプログラムを準備します。
// 1次関数のグラフを描く
void setup(){
size(500,500);
noLoop();
float x_range = 10.0; // x軸の表示範囲 -x_rangeからx_rangeまで
float y_range = 10.0; // y軸の表示範囲 -y_rangeからy_rangeまで
setAxes(x_range, y_range); // 座標軸の準備
noFill();
stroke(0,0,0);
// グラフの定義域
float x_l = -x_range; // 定義域の左端
float x_r = x_range; // 定義域の右端
int plot_num = 200; // グラフを描くための頂点の個数
// グラフを描画
float x, y; // 関数の座標
float X, Y; // キャンバス上の座標
beginShape();
for(int i=0; i<=plot_num; i++){
x = x_l + (x_r - x_l) / plot_num * i; // 関数のx座標
y = linearfunction(x); // 関数の値
// キャンバス上の座標位置に換算
X = width / 2.0 / x_range * x;
Y = height / 2.0 / y_range * y;
vertex(X, Y);
}
endShape();
}
// 1次関数の関数
float linearfunction(
float x
){
return 1.0/2.0 * x + 1.0;
}
ソースコード2 1次関数$${y=\frac{1}{2}x+1}$$を描くプログラム
このソースコード2を、スケッチ「drawLinearFunction」の
「drawLinearFunction」タブのテキストエディタ部分に書きます(図2)。
これを実行すると、図3のように、実行ウィンドウのキャンバス上に$${-10 \leq x \leq 10}$$の定義域に対して1次関数$${y=\frac{1}{2}x+1}$$のグラフを描きます。
2次関数のグラフを描く
次に、2次関数
$$
y=x^2+4x+3
$$
のグラフを描きます。
2次関数をプログラムの関数として準備
2次関数をプログラムの関数として準備します。
// 2次関数の関数
float quadraticfunction(
float x
){
return x*x + 4.0*x + 3.0;
}
ソースコード3 2次関数$${y=x^2+4x+3}$$の関数
2次関数のグラフを描く
スケッチ「drawQuadraticFunction」を準備し、その「drawQuadraticFunction」フォルダに「setAxes.pde」ファイルをコピーします。その上で、2次関数を描くプログラムを準備します。
// 2次関数のグラフを描く
void setup(){
size(500,500);
noLoop();
float x_range = 10.0; // x軸の表示範囲 -x_rangeからx_rangeまで
float y_range = 10.0; // y軸の表示範囲 -y_rangeからy_rangeまで
setAxes(x_range, y_range); // 座標軸の準備
noFill();
stroke(0,0,0);
// グラフの定義域
float x_l = -x_range; // 定義域の左端
float x_r = x_range; // 定義域の右端
int plot_num = 200; // グラフを描くための頂点の個数
// グラフを描画
float x, y; // 関数の座標
float X, Y; // キャンバス上の座標
beginShape();
for(int i=0; i<=plot_num; i++){
x = x_l + (x_r - x_l) / plot_num * i; // 関数のx座標
y = quadraticfunction(x); // 関数の値
// キャンバス上の座標位置に換算
X = width / 2.0 / x_range * x;
Y = height / 2.0 / y_range * y;
vertex(X, Y);
}
endShape();
}
// 2次関数の関数
float quadraticfunction(
float x
){
return x*x + 4.0*x + 3.0;
}
ソースコード4 2次関数$${y=x^2+4x+3}$$を描くプログラム
このソースコード4を、スケッチ「drawQuadraticFunction」の
「drawQuadraticFunction」タブのテキストエディタ部分に書きます(図4)。
これを実行すると、図5のように、実行ウィンドウのキャンバス上に$${-10 \leq x \leq 10}$$の定義域に対して2次関数$${y=x^2+4x+3}$$のグラフを描きます。なお、縦方向の表示範囲が$${-10 \leq y \leq 10}$$となっていますので、$${y>10}$$の範囲のグラフは表示されません。
関数の最大値と最小値
最後に、2次関数$${y=x^2+4x+3}$$の定義域$${-10 \leq x \leq 10}$$での最小値を、プログラムを作ってもとめてみます。
アルゴリズム設計
① 最小値を格納するfloat型の変数$${y_{\mathrm{min}}}$$を準備し、できるだけ大きな値(今回は表示範囲の最大値$${10}$$としています)で初期化しておきます。
② 定義域$${-10 \leq x \leq 10}$$をplot_num個に分割し、小さい方から順にその$${x}$$での関数の値をもとめ、その関数の値が$${y_{\mathrm{min}}}$$の値より小さければ、$${y_{\mathrm{min}}}$$をその時の関数の値で更新します。
③ 定義域全体で②を行った結果、最後に残った$${y_{\mathrm{min}}}$$の値が最小値となります。
最小値を求めるプログラム
上記のアルゴリズムをもとに、2次関数の最小値を求めるプログラムを作成します。
// 2次関数の最小値を求める
void setup(){
float x_range = 10.0; // x軸の表示範囲 -x_rangeからx_rangeまで
float y_range = 10.0; // y軸の表示範囲 -y_rangeからy_rangeまで
// グラフの定義域
float x_l = -x_range; // 定義域の左端
float x_r = x_range; // 定義域の右端
int plot_num = 200; // グラフを描くための頂点の個数
// グラフを描画
float x, y; // 関数の座標
float y_min = y_range; // 最小値 表示範囲の最大値で初期化
float x_min = 0.0; // 関数が最小値を取るときのxの値
for(int i=0; i<=plot_num; i++){
x = x_l + (x_r - x_l) / plot_num * i; // 関数のx座標
y = quadraticfunction(x); // 関数の値
if( y_min > y ){
y_min = y;
x_min = x;
}
}
println(x_min, y_min);
}
// 2次関数の関数
float quadraticfunction(
float x
){
return x*x + 4.0*x + 3.0;
}
ソースコード5 2次関数$${y=x^2+4x+3}$$の最小値を求めるプログラム
このソースコード5を、Processingの開発環境ウィンドウを開いて(スケッチ名を「minQuadraticFunction」としています)、テキストエディタ部分に書いて実行すると、図6のように、コンソールに$${-2.0 -1.0}$$と表示されます。これは2次関数$${y=x^2+4x+3}$$の最小値が$${-1}$$でそのときの$${x}$$の値が$${-2}$$となることを示しています。
なお、今回は2次関数$${y=x^2+4x+3}$$が下に凸のグラフになるため、最小値を求めましたが、最大値を求めたい場合も同様な方法で求めることができます。
グラフに最小値をプロットするプログラム
おまけとして、2次関数$${y=x^2+4x+3}$$のグラフに最小値の点をプロットするプログラムを作成します。それには、2次関数を描くプログラム(ソースコード4)に、2次関数の最小値を求めるプログラム(ソースコード5)を組み込んでいきます。
// 2次関数のグラフと最小値を描く
void setup(){
size(500,500);
noLoop();
float x_range = 10.0; // x軸の表示範囲 -x_rangeからx_rangeまで
float y_range = 10.0; // y軸の表示範囲 -y_rangeからy_rangeまで
setAxes(x_range, y_range); // 座標軸の準備
noFill();
stroke(0,0,0);
// グラフの定義域
float x_l = -x_range; // 定義域の左端
float x_r = x_range; // 定義域の右端
int plot_num = 200; // グラフを描くための頂点の個数
// グラフを描画
float x, y; // 関数の座標
float X, Y; // キャンバス上の座標
float y_min = y_range; // 最小値 表示範囲の最大値で初期化
float x_min = 0.0; // 関数が最小値を取るときのxの値
beginShape();
for(int i=0; i<=plot_num; i++){
x = x_l + (x_r - x_l) / plot_num * i; // 関数のx座標
y = quadraticfunction(x); // 関数の値
if( y_min > y ){
y_min = y;
x_min = x;
}
// キャンバス上の座標位置に換算
X = width / 2.0 / x_range * x;
Y = height / 2.0 / y_range * y;
vertex(X, Y);
}
endShape();
// 最小値を取るグラフ上の点をキャンバス上の座標位置に換算してプロット
stroke(255,0,0);
strokeWeight(5);
float X_min, Y_min;
X_min = width / 2.0 / x_range * x_min;
Y_min = height / 2.0 / y_range * y_min;
point(X_min, Y_min);
}
// 2次関数の関数
float quadraticfunction(
float x
){
return x*x + 4.0*x + 3.0;
}
ソースコード6 2次関数のグラフとその最小値を描くプログラム
スケッチ「drawQuadraticFunctionwithMin」を準備し、その「drawQuadraticFunctionwithMin」フォルダに「setAxes.pde」ファイルをコピーします。その上で、このソースコード6を、スケッチ「drawQuadraticFunctionwithMin」の
「drawQuadraticFunctionwithMin」タブのテキストエディタ部分に書いて実行すると、図7のように、2次関数のグラフが描かれ、その最小値を取る点が赤色で描かれます。
まとめ
今回は、数学Iで学ぶ「関数とグラフ」について、1次関数と2次関数のグラフを描くプログラムや2次関数の最小値を求めるプログラムなどを作成しました。
記事『高校数学をプログラミングで解く(数学I編)「1-0-2 グラフを描くための準備(その2)」』で導入した座標軸を描くための関数setAxesを利用する方法を復習しながら描いてみました。このようにプログラムを作成する際は以前作成したプログラムを関数化して再利用すると便利ですし、また間違いを少なくすることもできます。このような関数化して再利用することに慣れていってください。
参考文献
改訂版 教科書傍用 スタンダード 数学I(数研出版、ISBN9784410209178)
この記事が気に入ったらサポートをしてみませんか?