見出し画像

高校数学をプログラミングで解く(数学I編)「1-6 グラフと2次方程式」


はじめに

今回は、数学Iで学ぶ「グラフと2次方程式」について、2次関数のグラフの$${x}$$軸との共有点と2次方程式の実数解との関係を確かめるプログラムを作成していきます。

2次関数のグラフとx軸の共有点

2次関数のグラフの$${x}$$軸との共有点と2次方程式の実数解との関係
2次関数$${y=ax^2+bx+c}$$のグラフと$${x}$$軸に共有点があるとき、その共有点の$${x}$$座標は、2次方程式$${ax^2+bx+c=0}$$の実数解である。

今回は、以下の例題について実際に2次関数$${y=ax^2+bx+c}$$のグラフを描き、一方で2次方程式$${ax^2+bx+c=0}$$の実数解を求めて$${x}$$軸上にプロットすることで、共有点と実数解の関係が成り立っているかを確認してみます。

例題
次の2次方程式の実数解を求めて、2次関数のグラフの$${x}$$軸との共有点の関係を調べよ。
(1) $${x^2-2x = 0 \ ( \ \Rightarrow \ a=1, b=-2, c=0 \ )}$$ 
(2) $${x^2-2x+1 = 0 \ ( \ \Rightarrow \ a=1, b=-2, c=1 \ )}$$
(3) $${x^2-2x+2 = 0 \ ( \ \Rightarrow \ a=1, b=-2, c=2 \ )}$$

2次関数のグラフを描くプログラム(復習)

記事『高校数学をプログラミングで解く(数学I編)「1-2 2次関数のグラフ」』で、2次関数のグラフを描くプログラムは作成していますので、ここでは、それを再利用します。なお、2次関数は例題(1)に合わせて、$${a=1, b=-2, c=0}$$としています。

// 2次関数y=ax^2+bx+cのグラフのx軸との共有点と
// 2次方程式ax^2+bx+c=0の実数解との関係
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; // グラフを描くための頂点の個数  
  
  // 2次関数の係数
  float a = 1.0;
  float b = -2.0;
  float c = 0.0;
  
  // グラフを描画
  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(a, b, c, x); // 関数の値
    // キャンバス上の座標位置に換算
    X = width / 2.0 / x_range * x;
    Y = height / 2.0 / y_range * y;
    vertex(X, Y);
  }
  endShape();
  
}

// 2次関数の一般形
float quadraticfunction(
  float a, // 2次の係数
  float b, // 1次の係数
  float c, // 定数項
  float x
){
  return a*x*x + b*x + c;
}

ソースコード1 2次関数$${y=ax^2+bx+c}$$を描くプログラム

スケッチ「drawQuadraticFunctionwithCommonPoint」を準備し、その「drawQuadraticFunctionwithCommonPoint」フォルダに「setAxes.pde」ファイルをコピーして、ソースコード1を、「drawQuadraticFunctionwithCommonPoint」タブのテキストエディタ部分に書いて実行すると、図1のように、実行ウィンドウのキャンバスに例題(1)の2次関数$${y=x^2-2x}$$のグラフが描かれます。

図1 2次関数のグラフを描画

2次方程式の実数解を求めるプログラム(復習)

記事『高校数学をプログラミングで解く(数学I編)「1-5 2次方程式」』で、2次方程式の実数解を求めるプログラムは作成していますので、それを再利用します。

// 2次方程式の実数解を求める
void setup(){

  // 2次方程式ax^2+bx+c=0の係数
  float a = 1.0;
  float b = -2.0;
  float c = 0.0;  
  
  // 判別式
  float D = b*b-4.0*a*c;
  
  // 2次方程式の解の個数を求め、その解も求める
  if( D > 0 ){
    float x1, x2;
    x1 = (-b + sqrt(D))/2.0/a;
    x2 = (-b - sqrt(D))/2.0/a;
    print("異なる2つの実数解をもつ: ");
    println(x1, x2);
  } else if( D == 0 ){
    float x1;
    x1 = -b/2.0/a;
    print("ただ1つの実数解(重解)をもつ: ");
    println(x1);
  } else {
    println("実数解を持たない");
  }   
}

ソースコード2 解の公式による2次方程式の解を求めるプログラム

2次関数のグラフと2次方程式の実数解をプロットするプログラム

上記、2つのプログラムを組み合わせることで、2次関数のグラフと2次方程式の実数解をプロットするプログラムを作成することができます。
ただ、ソースコード2は求めた実数解をコンソールに出力するプログラムです。今回は、実数解を$${x}$$軸上の点としてプロットしていくので、ソースコード2をプロットするように書き換えた上で、ソースコード1に追記していきます。

// 2次関数y=ax^2+bx+cのグラフのx軸との共有点と
// 2次方程式ax^2+bx+c=0の実数解との関係
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; // グラフを描くための頂点の個数  
  
  // 2次関数の係数
  float a = 1.0;
  float b = -2.0;
  float c = 0.0;
  
  // グラフを描画
  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(a, b, c, x); // 関数の値
    // キャンバス上の座標位置に換算
    X = width / 2.0 / x_range * x;
    Y = height / 2.0 / y_range * y;
    vertex(X, Y);
  }
  endShape();
  
  // 判別式
  float D = b*b-4.0*a*c;
  
  stroke(255,0,0);
  strokeWeight(5);
  
  // 2次方程式の解の個数に応じて、その実数解をx軸上にプロットする
  if( D > 0 ){
    float x1, x2;
    float X1, X2;
    x1 = (-b + sqrt(D))/2.0/a;
    x2 = (-b - sqrt(D))/2.0/a;
    // キャンバス上の座標位置に換算
    X1 = width / 2.0 / x_range * x1;
    X2 = width / 2.0 / x_range * x2;
    point(X1, 0.0);
    point(X2, 0.0);
  } else if( D == 0 ){
    float x1;
    float X1;
    x1 = -b/2.0/a;
    // キャンバス上の座標位置に換算
    X1 = width / 2.0 / x_range * x1;
    point(X1, 0.0);    
  } else {
    println("実数解を持たない");
  }   
  
  
}

// 2次関数の一般形
float quadraticfunction(
  float a, // 2次の係数
  float b, // 1次の係数
  float c, // 定数項
  float x
){
  return a*x*x + b*x + c;
}

ソースコード3 2次関数のグラフと2次方程式の実数解をプロットするプログラム

2次関数のグラフのx軸との共有点と2次方程式の実数解との関係を確認する

スケッチ「drawQuadraticFunctionwithCommonPoint」の「drawQuadraticFunctionwithCommonPoint」タブのテキストエディタ部分を、ソースコード3に書き換えて実行すると、図2のように、実行ウィンドウのキャンバスに例題(1)の2次関数$${y=x^2-2x}$$のグラフを描くとともに2次方程式の実数解($${x=2, \ 0}$$)を$${x}$$軸上の点(赤色)としてプロットします。

図2 2次関数のグラフと2次方程式の2つの異なる実数解

図2を見ると、2次方程式の2つの実数解($${x=2, \ 0}$$)が2次関数の$${x}$$軸との2つの共有点の位置と一致していることがわかります。

また、ソースコード3の2次方程式の係数の部分を例題(2)に合わせて、$${a=1, b=-2, c=1}$$として実行すると、図3のように、実行ウィンドウのキャンバスに例題(2)の2次関数$${y=x^2-2x+1}$$のグラフを描くとともに2次方程式の実数解($${x=1}$$、重解)を$${x}$$軸上の点(赤色)としてプロットします。

図3 2次関数のグラフと2次方程式の1つの実数解(重解)

図3を見ると、2次方程式の1つの実数解($${x=1}$$、重解)が2次関数の$${x}$$軸との1つの共有点の位置と一致していることがわかります。

最後に、ソースコード3の2次方程式の係数の部分を例題(3)に合わせて、$${a=1, b=-2, c=2}$$として実行すると、図4のように、実行ウィンドウのキャンバスに例題(3)の2次関数$${y=x^2-2x+2}$$のグラフのみ描かれます。2次方程式$${x^2-2x+2=0}$$は実数解をもたないので、$${x}$$軸上の点はプロットできません。

図4 2次関数のグラフ、2次方程式の実数解はなし

図4を見ると、2次方程式の実数解はないので、2次関数の$${x}$$軸との共有点はありません。

以上のことから、最初に述べた『2次関数のグラフの$${x}$$軸との共有点と2次方程式の実数解との関係』が成り立っていることがわかります。

応用例:放物線と直線との共有点

では、『2次関数のグラフの$${x}$$軸との共有点と2次方程式の実数解との関係』の応用例として、次の問題を考えてみます。

問題
次の放物線と直線は共有点をもつか。持つ場合はその共有点をプロットせよ。

$$
y = x^2-2x, \ \ y = x
$$

この問題を解くプログラムはソースコード3を再利用して作成することができます。ポイントは、共有点は$${y = x^2-2x}$$と$${y = x}$$との連立方程式の実数解と一致するということです。

// 放物線y=ax^2+bx+cと直線y=mx+nの共有点
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; // グラフを描くための頂点の個数  
  
  // 2次関数の係数
  float a = 1.0;
  float b = -2.0;
  float c = 0.0;
  
  // 2次関数のグラフを描画
  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(a, b, c, x); // 関数の値
    // キャンバス上の座標位置に換算
    X = width / 2.0 / x_range * x;
    Y = height / 2.0 / y_range * y;
    vertex(X, Y);
  }
  endShape();
  
  // 直線の係数
  float m = 1.0;
  float n = 0.0;
  
  // 直線の両端の座標
  float xl, yl;
  float xr, yr;
  xl = -x_range;
  yl = linearfunction(m, n, xl);
  xr = x_range;
  yr = linearfunction(m, n, xr);
  // キャンバス上の座標位置に換算
  float Xl, Yl, Xr, Yr;
  Xl = width / 2.0 / x_range * xl;
  Yl = height / 2.0 / y_range * yl;
  Xr = width / 2.0 / x_range * xr;
  Yr = height / 2.0 / y_range * yr;
  // 直線のグラフを描画
  line(Xl, Yl, Xr, Yr); 
  
  // 2次関数と直線を連立させて解く  
  // →2次方程式ax^2+(b-m)x+(c-n)=0を解く
  float ap = a;
  float bp = b-m;
  float cp = c-n;
  
  // 判別式
  float D = bp*bp-4.0*ap*cp;
  
  stroke(255,0,0);
  strokeWeight(5);
  
  // 2次方程式の解の個数に応じて、共有点にプロットする
  if( D > 0 ){
    float x1, x2, y1, y2;
    float X1, X2, Y1, Y2;
    x1 = (-bp + sqrt(D))/2.0/ap;
    y1 = linearfunction(m, n, x1);
    x2 = (-bp - sqrt(D))/2.0/ap;
    y2 = linearfunction(m, n, x2);    
    // キャンバス上の座標位置に換算
    X1 = width / 2.0 / x_range * x1;
    Y1 = height / 2.0 / y_range * y1;
    X2 = width / 2.0 / x_range * x2;
    Y2 = height / 2.0 / y_range * y2;    
    point(X1, Y1);
    point(X2, Y2);
  } else if( D == 0 ){
    float x1, y1;
    float X1, Y1;
    x1 = -bp/2.0/ap;
    y1 = linearfunction(m, n, x1);
    // キャンバス上の座標位置に換算
    X1 = width / 2.0 / x_range * x1;
    Y1 = height / 2.0 / y_range * y1;
    point(X1,Y1);    
  } else {
    println("実数解を持たない");
  }   
 
}

// 2次関数の一般形
float quadraticfunction(
  float a, // 2次の係数
  float b, // 1次の係数
  float c, // 定数項
  float x
){
  return a*x*x + b*x + c;
}

// 直線を表す関数
float linearfunction(
  float m, // 傾き
  float n, // 切片
  float x
){
  return m*x+n;
}

ソースコード4 放物線と直線との共有点をプロットするプログラム

スケッチ「drawQuadraticFunctionandLine」を準備し、その「drawQuadraticFunctionandLine」フォルダに「setAxes.pde」ファイルをコピーして、ソースコード4を、「drawQuadraticFunctionandLine」タブのテキストエディタ部分に書いて実行すると、図5のように、実行ウィンドウのキャンバスに問題の放物線$${y=x^2-2x}$$と直線$${y=x}$$のグラフが描かれるとともにそれらの共有点が赤色でプロットされます。

図5 放物線と直線との共有点をプロット

まとめ

今回は、数学Iで学ぶ「グラフと2次方程式」について、2次関数のグラフの$${x}$$軸との共有点と2次方程式の実数解との関係を確かめるプログラムを作成しました。
2次関数のグラフの$${x}$$軸との共有点と2次方程式の実数解との関係を確かめることは比較的簡単ではありますが、プログラムで実際に2次関数のグラフを描き、2次方程式の実数解を求めてプロットして確かめることは別の観点から見ることができるので、理解を深める上で役に立ちます。
また、今回のプログラム(ソースコード3)はこれまで別の記事で紹介してきたプログラムを再利用して作成しました。また、応用例として紹介した放物線と直線の共有点をプロットするプログラム(ソースコード4)はソースコード3を再利用して作成しています。プログラムを再利用することはプログラミング作成の効率を上げますので、このような使い方にも慣れていってください。

参考文献

改訂版 教科書傍用 スタンダード 数学I(数研出版、ISBN9784410209178)


この記事が気に入ったらサポートをしてみませんか?