二次関数の最大・最小
区間における最大・最小
たとえば「ある商品の価格 円(100円〜500円の範囲で)を変えたとき、売上 円はどう変わるか?」という問いを考えてみましょう。価格の「範囲」が決まっているとき、売上が最大・最小になる価格はどこでしょうか?
これが二次関数の最大値・最小値を区間で求める問題の発想です。
二次関数 の最大値・最小値を求めるときは、定義域(区間)を必ず確認する必要があります。
考え方の基本は次の通りです:
-
定義域が実数全体 のとき
- :最小値 ( のとき)、最大値なし
- :最大値 ( のとき)、最小値なし
-
定義域が閉区間 のとき → 頂点 が区間内か外かで場合分けが必要
場合分けの考え方
谷型()の放物線で考えましょう。谷の最も低い点が「定義域の範囲内にあるか、範囲外か」によって最小値の場所が変わります。
で (下に凸)、定義域 の場合:
最小値
| 頂点の位置 | 最小値をとる |
|---|---|
| (頂点が区間内) | 、最小値 (谷の底が範囲内にある) |
| (頂点が区間左外) | (谷の底が左に外れているので、左端が一番低い) |
| (頂点が区間右外) | (谷の底が右に外れているので、右端が一番低い) |
最大値
下に凸では、谷の底(頂点)から最も遠い端点で最大値をとります。遠い端点ほど高く上がっているからです。
インタラクティブデモ:区間を動かして最大・最小を確認
マウスを左右に動かすと、区間の右端 が変わります。頂点が区間の内外に出るとき、最小値をとる点がどう変化するかを観察してください。赤い星が最小値点、黄色の星が最大値点です。
function loop() {
ctx.clearRect(0, 0, W, H);
var ox = W / 2, oy = H / 2 + 40;
var scale = 55;
var a = 0.8, p = 0.5, q = -2;
var alpha = -2.0;
var beta = alpha + 0.5 + (mx / W) * 4.5;
if (beta <= alpha + 0.3) beta = alpha + 0.3;
function toScreen(x, y) {
return { sx: ox + x * scale, sy: oy - y * scale };
}
function f(x) { return a * (x - p) * (x - p) + q; }
// Grid
ctx.strokeStyle = 'rgba(255,255,255,0.06)';
ctx.lineWidth = 1;
for (var gx = -6; gx <= 6; gx++) {
var gs = toScreen(gx, 0);
ctx.beginPath(); ctx.moveTo(gs.sx, 0); ctx.lineTo(gs.sx, H); ctx.stroke();
}
for (var gy = -3; gy <= 4; gy++) {
var gs2 = toScreen(0, gy);
ctx.beginPath(); ctx.moveTo(0, gs2.sy); ctx.lineTo(W, gs2.sy); ctx.stroke();
}
// Axes
ctx.strokeStyle = 'rgba(255,255,255,0.3)';
ctx.lineWidth = 1.5;
ctx.beginPath(); ctx.moveTo(0, oy); ctx.lineTo(W, oy); ctx.stroke();
ctx.beginPath(); ctx.moveTo(ox, 0); ctx.lineTo(ox, H); ctx.stroke();
// Full parabola (dim)
ctx.strokeStyle = 'rgba(79,195,247,0.2)';
ctx.lineWidth = 1.5;
ctx.beginPath();
var st = false;
for (var xi = -6; xi <= 6; xi += 0.03) {
var yi = f(xi);
if (Math.abs(yi) > 7) { st = false; continue; }
var s = toScreen(xi, yi);
if (!st) { ctx.moveTo(s.sx, s.sy); st = true; } else ctx.lineTo(s.sx, s.sy);
}
ctx.stroke();
// Parabola on interval (bright)
ctx.strokeStyle = '#4fc3f7';
ctx.lineWidth = 3;
ctx.beginPath();
var st2 = false;
for (var xi2 = alpha; xi2 <= beta; xi2 += 0.02) {
var yi2 = f(xi2);
var s2 = toScreen(xi2, yi2);
if (!st2) { ctx.moveTo(s2.sx, s2.sy); st2 = true; } else ctx.lineTo(s2.sx, s2.sy);
}
ctx.stroke();
// Interval bracket on x-axis
var sa = toScreen(alpha, 0), sb = toScreen(beta, 0);
ctx.strokeStyle = '#81c784';
ctx.lineWidth = 3;
ctx.beginPath(); ctx.moveTo(sa.sx, oy - 10); ctx.lineTo(sa.sx, oy + 10); ctx.stroke();
ctx.beginPath(); ctx.moveTo(sb.sx, oy - 10); ctx.lineTo(sb.sx, oy + 10); ctx.stroke();
ctx.beginPath(); ctx.moveTo(sa.sx, oy); ctx.lineTo(sb.sx, oy); ctx.stroke();
ctx.fillStyle = '#81c784';
ctx.font = '13px sans-serif';
ctx.fillText('α=' + alpha.toFixed(1), sa.sx - 14, oy + 26);
ctx.fillText('β=' + beta.toFixed(2), sb.sx - 14, oy + 26);
// Min point
var xMin, yMin;
if (p >= alpha && p <= beta) {
xMin = p; yMin = q;
} else if (p < alpha) {
xMin = alpha; yMin = f(alpha);
} else {
xMin = beta; yMin = f(beta);
}
// Max point
var yA = f(alpha), yB = f(beta);
var xMax = yA > yB ? alpha : beta;
var yMax = Math.max(yA, yB);
// Draw min star (red)
var sMin = toScreen(xMin, yMin);
ctx.fillStyle = '#ef5350';
ctx.font = '22px sans-serif';
ctx.fillText('★', sMin.sx - 11, sMin.sy + 8);
ctx.fillStyle = '#ef9a9a';
ctx.font = '12px sans-serif';
ctx.fillText('最小値 ' + yMin.toFixed(2), sMin.sx - 20, sMin.sy - 14);
// Draw max star (yellow)
var sMax = toScreen(xMax, yMax);
ctx.fillStyle = '#ffeb3b';
ctx.font = '22px sans-serif';
ctx.fillText('★', sMax.sx - 11, sMax.sy + 8);
ctx.fillStyle = '#fff176';
ctx.font = '12px sans-serif';
ctx.fillText('最大値 ' + yMax.toFixed(2), sMax.sx + 6, sMax.sy - 6);
// Vertex dot
var sv = toScreen(p, q);
ctx.fillStyle = 'rgba(255,255,255,0.5)';
ctx.beginPath(); ctx.arc(sv.sx, sv.sy, 4, 0, Math.PI * 2); ctx.fill();
// Info
ctx.fillStyle = 'rgba(0,0,0,0.6)';
ctx.beginPath(); ctx.roundRect(10, 10, 230, 80, 8); ctx.fill();
ctx.fillStyle = '#4fc3f7';
ctx.font = 'bold 13px monospace';
ctx.fillText('y = ' + a + '(x - ' + p + ')² + (' + q + ')', 18, 32);
ctx.fillStyle = 'rgba(255,255,255,0.7)';
ctx.font = '12px sans-serif';
ctx.fillText('区間: [' + alpha.toFixed(1) + ', ' + beta.toFixed(2) + ']', 18, 52);
var inside = p >= alpha && p <= beta;
ctx.fillStyle = inside ? '#a5d6a7' : '#ef9a9a';
ctx.fillText('頂点 x=' + p + ' は区間' + (inside ? '内' : '外'), 18, 72);
requestAnimationFrame(loop);
}
loop(); 具体的な解法手順
例題
()の最大値・最小値を求めよ。
手順①:平方完成
頂点 、下に凸(谷型)。「 のとき一番低い」という形です。
手順②:頂点の区間チェック
なので頂点 は区間 の内側にあります。つまり「谷の底が見える」状態です。
手順③:最小値
谷の底が区間内にあるので、 のとき最小値 。
手順④:最大値
谷型では端点が高くなります。両端を計算します:
- :
- :
遠い方()が高いので、最大値は ( のとき)。
頂点が区間外のケース
例題
()の最小値を求めよ。
頂点 は区間 の左外にあります。谷の底が「左に外れている」ので、区間内で一番低い点は、谷の底に一番近い端点である です。
下に凸なので、区間内では頂点に近い端点が最小:
- :
- :
よって最小値は ( のとき)。
練習問題
- ()の最大値・最小値を求めよ。
- ()の最大値・最小値を求めよ。
- ()の最大値・最小値を求めよ。
解答
- 。頂点 は区間 内。最大値 ()、最小値 ()
- 。頂点 は区間右端。最小値 ()、最大値 ()
- 。頂点 は左端。最小値 ()、最大値 ()
まとめ
| 状況 | 最小値の場所() |
|---|---|
| 頂点が区間内 | 頂点(谷の底) |
| 頂点が区間左外 | 左端(谷の底に最も近い端) |
| 頂点が区間右外 | 右端(谷の底に最も近い端) |
最大値は常に「頂点から遠い方の端点」で得られます( の場合)。遠い端点ほど、谷の斜面をより多く上った場所にあるからです。