関数の連続性
連続性の定義
「グラフが途切れないで描ける」状態を連続と言います。鉛筆を紙から離さずにスイスイと描けるなら連続です。逆に途中でペンを上げなければならない点があれば、そこが不連続の点です。
前回は「極限」を学びました。今回はそれを発展させて連続性(continuity)を定義します。
関数 が で連続であるとは、次の 3 条件がすべて成立することです:
- が定義されている(その点で値がある)
- が存在する(近づいたときの行き先がある)
- (行き先と実際の値が一致する)
一言で言えば「グラフを鉛筆で紙から離さずに描ける」状態です。
不連続の種類
除去可能不連続(Removable Discontinuity)
極限値は存在するが、 が定義されていないか、 となっている場合。「穴」が一つあるイメージです。
での値を と定義し直せば連続になるため「除去可能」と呼びます。穴を埋めるだけで修復できるタイプです。
跳躍不連続(Jump Discontinuity)
左極限と右極限は存在するが、両者が一致しない場合。グラフが「ジャンプ」します。
たとえばエレベーターのボタンを押した瞬間を想像してください——押す前と押した後で床の数字がパッと変わります。値が「飛んでいる」状態です。
で 、 となり不一致。
無限不連続(Infinite Discontinuity)
となる場合。 の が典型例。グラフが垂直に上や下に向かって突き抜けていきます。
デモ:不連続点をインタラクティブに確認
マウスを左右に動かして を動かしてください。不連続点( の跳躍、 の除去可能不連続)を通過するときにグラフがどう変わるかを観察できます。
- 白丸(開円):その点での値がない(定義されていない)
- 青丸(閉円):その点での値がある
function loop() {
ctx.clearRect(0, 0, W, H);
var scale=55;
var ox=W/2, oy=H/2;
function toSx(x){return ox+x*scale;}
function toSy(y){return oy-y*scale;}
function drawAxes(){
ctx.strokeStyle='rgba(255,255,255,0.15)';
ctx.lineWidth=1;
ctx.beginPath();ctx.moveTo(0,oy);ctx.lineTo(W,oy);ctx.stroke();
ctx.beginPath();ctx.moveTo(ox,0);ctx.lineTo(ox,H);ctx.stroke();
ctx.fillStyle='rgba(255,255,255,0.3)';
ctx.font='10px monospace';
ctx.textAlign='center';
for(var i=-4;i<=4;i++){
if(i===0)continue;
ctx.fillText(i,toSx(i),oy+14);
}
ctx.textAlign='right';
for(var j=-3;j<=3;j++){
if(j===0)continue;
ctx.fillText(j,ox-6,toSy(j)+4);
}
}
// Piecewise function:
// x < -2 : 0.3*x + 1 (left branch)
// -2 <= x < 1 : 0.5*(x+2) - 1 (middle branch, open at x=1)
// x >= 1 : -0.5*x + 2 (right branch, closed at x=1 with different value = 1.5)
function f(x){
if(x<-2) return 0.3*x+2.4;
if(x<1) return 0.5*(x+2)-2;
return -0.4*x+2;
}
ctx.fillStyle='#0d1117';
ctx.fillRect(0,0,W,H);
drawAxes();
// Draw three segments separately
var col='#4fc3f7';
ctx.strokeStyle=col; ctx.lineWidth=2;
// Segment 1: x < -2
ctx.beginPath();
var first=true;
for(var xi=-W/2;xi<=-2*scale-3;xi+=1){
var x=xi/scale;
var y=f(x);
if(first){ctx.moveTo(toSx(x),toSy(y));first=false;}
else ctx.lineTo(toSx(x),toSy(y));
}
ctx.stroke();
// Segment 2: -2 <= x < 1
ctx.beginPath();
first=true;
for(var xi2=-2*scale;xi2<=1*scale-3;xi2+=1){
var x2=xi2/scale;
var y2=f(x2);
if(first){ctx.moveTo(toSx(x2),toSy(y2));first=false;}
else ctx.lineTo(toSx(x2),toSy(y2));
}
ctx.stroke();
// Segment 3: x >= 1
ctx.beginPath();
first=true;
for(var xi3=1*scale;xi3<=W/2;xi3+=1){
var x3=xi3/scale;
var y3=f(x3);
if(first){ctx.moveTo(toSx(x3),toSy(y3));first=false;}
else ctx.lineTo(toSx(x3),toSy(y3));
}
ctx.stroke();
// Jump discontinuity at x=-2
// left limit: 0.3*(-2)+2.4 = 1.8
// right limit: 0.5*(-2+2)-2 = -2
var jumpLeft=0.3*(-2)+2.4;
var jumpRight=0.5*(0)-2;
// open circle at left approach value (x=-2, from left)
ctx.beginPath(); ctx.arc(toSx(-2),toSy(jumpLeft),5,0,Math.PI*2);
ctx.strokeStyle='#ff7043'; ctx.lineWidth=2; ctx.stroke();
ctx.fillStyle='#0d1117'; ctx.fill();
// closed circle at right value (x=-2, right branch takes over)
ctx.beginPath(); ctx.arc(toSx(-2),toSy(jumpRight),5,0,Math.PI*2);
ctx.fillStyle='#4fc3f7'; ctx.fill();
// Removable discontinuity at x=1
// limit from left: 0.5*(1+2)-2 = -0.5
var limAt1 = 0.5*(3)-2;
// actual value from right branch: -0.4*1+2 = 1.6
var valAt1 = -0.4*1+2;
// open circle at limit
ctx.beginPath(); ctx.arc(toSx(1),toSy(limAt1),5,0,Math.PI*2);
ctx.strokeStyle='#ff7043'; ctx.lineWidth=2; ctx.stroke();
ctx.fillStyle='#0d1117'; ctx.fill();
// closed circle at actual defined value
ctx.beginPath(); ctx.arc(toSx(1),toSy(valAt1),5,0,Math.PI*2);
ctx.fillStyle='#4fc3f7'; ctx.fill();
// Mouse interaction
var xm=(mx-ox)/scale;
var xm2=Math.max(-4.5,Math.min(4.5,xm));
var ym=f(xm2);
if(isFinite(ym)){
ctx.setLineDash([4,4]);
ctx.strokeStyle='rgba(255,202,40,0.4)';
ctx.lineWidth=1;
ctx.beginPath();ctx.moveTo(toSx(xm2),oy);ctx.lineTo(toSx(xm2),toSy(ym));ctx.stroke();
ctx.beginPath();ctx.moveTo(ox,toSy(ym));ctx.lineTo(toSx(xm2),toSy(ym));ctx.stroke();
ctx.setLineDash([]);
ctx.beginPath(); ctx.arc(toSx(xm2),toSy(ym),5,0,Math.PI*2);
ctx.fillStyle='#ffca28'; ctx.fill();
}
// Legend
ctx.fillStyle='#ff7043';
ctx.font='12px sans-serif';
ctx.textAlign='left';
ctx.fillText('○ 開円 = その点での値なし(不連続)',10, H-40);
ctx.fillStyle='#4fc3f7';
ctx.fillText('● 閉円 = その点での値あり',10, H-20);
// Annotations
ctx.fillStyle='rgba(255,112,67,0.9)';
ctx.font='bold 11px sans-serif';
ctx.textAlign='center';
ctx.fillText('跳躍不連続',toSx(-2),toSy(jumpLeft)-16);
ctx.fillText('除去可能不連続',toSx(1),toSy(limAt1)-16);
requestAnimationFrame(loop);
}
loop(); 連続関数の性質
連続関数には非常に便利な定理が成立します。
中間値の定理(Intermediate Value Theorem)
が で連続で ならば、 と の間の任意の値 に対して、 となる が少なくとも 1 つ存在する。
これは「グラフが切れていなければ、必ずどこかで横線を横切る」という直感的な事実です。
身近な例で考えてみましょう——「朝は気温 15°、昼は気温 25°」とすると、その間のどこかで必ず気温が 20° だった瞬間があります。グラフが連続(途切れない)なら、その間の値は全て通るはずです。
方程式の解の存在証明(例: が解を持つ)に利用されます。
最大値・最小値定理(Extreme Value Theorem)
が閉区間 で連続ならば、 はその区間内で最大値と最小値を取る。
「閉じた区間で連続なら、最高点と最低点が必ず存在する」——これも直感的に納得できますね。
多項式・三角関数は連続
次の関数はすべての実数上で連続です:
- 多項式 (どんな多項式もグラフは途切れない)
- 三角関数 (波のような滑らかな曲線)
- 指数関数 (右上がりの滑らかな曲線)
一方、 は 、すなわち で不連続(無限不連続)になります。分母がゼロになるところで値が無限大に発散するためです。
まとめ
| 不連続の種類 | 極限値 | 関数値 | 特徴 |
|---|---|---|---|
| 除去可能 | 存在する | 異なるか未定義 | 穴が 1 つ——値を定義し直せば修復できる |
| 跳躍 | 左右が不一致 | どちらかと一致か未定義 | グラフがジャンプ——エレベーターの階表示のよう |
| 無限 | 未定義 | 垂直漸近線——グラフが垂直に突き抜ける |
次回は、極限の概念をさらに発展させて微分の定義を学びます——「瞬間の変化率」を厳密に捉える差分商のアイデアです。