−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
   応用数学II                        1995.11.30-12/1
   15.実践−幾何学IIを素材に(1)−             飯島
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

15−1 はじめに

 「課題」を探そうねということなんだけど,なかなか難しいようです。まあ,これはみ なさんだけに始まったことではありません。               そういう練習をしていない ということなんで,               自分なりに問題を作ろう という経験をあまり持ったことのない人は,たとえ学校の教員であっても,なかなか「適 切な問題」を作ることができないということはよくあります。しかし, +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ |       創造的であるためには,問題発見が重要な鍵を握る        | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ ということを理解してください。そして, +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ |           適切な問題を作るためのノウハウ            | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ を自分なりに確立してください。せめて卒業するまでには。  まあ,そういうことの必要性を痛切に感じたこと,そして一方で,「幾何学II」が分か らんという声を少し聞くものですから,         幾何学IIを素材としたいくつかの実践的アプローチ を何回かやってみたいと思います。多少難しい部分も一気にやっちゃうかもしれないし, 逆に,プログラミングの観点から考えると大したことのないものが出てくることもありう るけれども,             現実の問題から出発した問題解決 というものは,概してそういうものです。

15−2 「適切な」問題とは(1)

 さて,前述でも,「適切な問題」という言葉が出てきました。どうしてでしょう。それ は,こういう事情からです。つまり,  ・問題を発見することは簡単だ。 そう,問題はいくらでも作れます。しかし,  ・それらの中のほとんどの問題は,    答えが明白過ぎて,考えるに値しない問題    取り組みようがなくて,やはり考えてもしょうがない問題 なんです。たとえば,みなさんにとっては,   「1+4=?」   「数学とはなにか」,「人生の意味は」,「誰と結婚したらいいだろう」 あたりは,これらの部類でしょう。それぞれ問題には,「適時性」があります。  「誰と結婚したらいいだろう」 という問題は,今はほとんどの人にとっては,「考えてもしょうがない(かもしれない) 」問題ですが,5年以内には,切実な問題になるでしょう。また,その問題そのものは手 の出しようがなくても,それに関連して,考えるに値する問題があったりします。たとえ ば,  「誰と付き合ったらいいだろう」 というのは,現在のみなさんの多くにとって,結構切実な問題なんじゃないでしょうか。 あるいは,  「数学とは何か」 というのは,手が出ないかもしれないが,  「幾何学IIの主題はなんだろう」 という程度だったら,それなりの解答が出てきます。そして,そのような解答を積み重ね ていくと,自分なりに,「数学とは何か」に対する答えが少しずつ形成されていくことで しょう。そういうようなものなんです。いずれにしても,         本当の問題というのは,「与えられる」ものではない ということを自覚しましょう。そして,            問題とは,自分で「育てる」ものである という実感を持ってください。

15−3 「適切な」問題とは(2)

 さて,上記は一般論でした。この授業は「応用数学」です。そういう意味では,「コン ピュータを使って数学の問題を考えるときには,どういう観点で問題を作るといいんだろ うか」ということになります。  (1) やらない方がいいこと  ・「分かっていること」しか見つからないような問題はやらない  ・「原理が分からないようなこと」もやらない  (2) やった方がいいこと  ・「原理は分かっているんだけれども,どうもしっくりこないような場合について,具    体的な場合を調べてみる」  ・「原理は分かるけれども,結果がどうなるか分からないような場合について調べてみ    る」  ・その結果の観察を基に,新しい数学の問題を考える  たとえば,「幾何学II」のテキストから考えてみましょう。2班の方の私の授業の中で は,例えば,次の内容は,「?」という感じでした。  (1)p.16 離心率の定義  (2)p.18     例題II 直線が放物線と交わりつつ平行移動するときの弦の中点の軌跡は?  ある意味では,これらは両方とも「頭」だけでも理解してほしい内容です。しかし,「 手」あるいは,「手」の代わりとしての「コンピュータ」を使うと,理解の側面も変わる かもしれない内容でもあります。                「え,どういうこと」 と思ったときに,               「理論的に理解すること」 は必ずしなければならない内容だけれども,それと一緒に,              「実際に実験をしてみること」 も一つの手だと言えるわけで,そういうところに,コンピュータ向きの問題があるわけで す。

15−4 離心率について考える

(1) 出発点  まずは,離心率について考えましょう。定義は,            焦点との距離           −−−−−−−−=e            準線との距離 において,eが一定になるような点の集合が二次曲線になるというわけです。それをその ままプログラム化すると,  eの入力(たとえば1)  いろいろな点について,   eを計算し,   e=1だったら,点を描く というような流れになります。後は,eの計算の中身,つまり焦点との距離をどう計算す るか,また準線との距離をどう計算するかという問題になります。 (2) 予想される問題点  数学的には,これでいいですし,またこれをきちんと実現するのは意味があることです が,陰関数の描画のときにも学習したように,問題点があります。  ・e=1(ぴったり)という点は,実はほとんどない   → e−1<ε の「範囲」について描画することが必要  ・結構時間がかかる (3) たとえば  例えば,次のようなプログラムを暫定的に作り,その様子を観察して,「次」を考える というのも一つの手です。   SCREEN 12   MaxOfX = 15   Dwidth = 2   DO     CLS     MaxOfY = MaxOfX * 480 / 640     dp = MaxOfX / 320     WINDOW (-MaxOfX, MaxOfY)-(MaxOfX, -MaxOfY)                             −+     LINE (-MaxOfX, 0)-(MaxOfX, 0)          | なくてもいい     FOR i = -INT(MaxOfX) TO INT(MaxOfX)       |       LINE (i, 5 * dp)-(i, -5 * dp)        |     NEXT                       |                              |     LINE (0, -MaxOfY)-(0, MaxOfY)          |     FOR i = -INT(MaxOfY) TO INT(MaxOfY)       |       LINE (5 * dp, i)-(-5 * dp, i)        |     NEXT                       |                             −+     FOR x = -MaxOfX TO MaxOfX STEP dp * Dwidth       FOR y = -MaxOfY - dp TO MaxOfY STEP dp * Dwidth         z = e(x, y)         SELECT CASE z             −+こういうのを           CASE IS < 0: PSET (x, y), 1     |Select文と言う           CASE IS < .5: PSET (x, y), 2     |適当に変えてみよう           CASE IS < 1: PSET (x, y), 3     |           CASE IS < 1.5: PSET (x, y), 4    |           CASE IS < 2: PSET (x, y), 5     |           CASE IS < 5: PSET (x, y), 6     |           CASE ELSE: PSET (x, y), 7      |         END SELECT               −+       NEXT     NEXT Restart:                        −+     LOCATE 1, 1                   |以前の陰関数のものを     PRINT "M:MaxOfX, D:Dots for drawing, Q:Quit"   |再利用した。     a$ = UCASE$(INPUT$(1))              |     SELECT CASE a$                  |       CASE "M"                   |         INPUT "MaxOfX"; MaxOfX          |         IF MaxOfX <= 0 THEN MaxOfX = 10     |       CASE "Q": EXIT DO              |       CASE "D"                   |         PRINT "How many dot ?"          |         INPUT Dwidth               |         IF Dwidth < 1 THEN Dwidth = 1      |       CASE ELSE                  |         BEEP                   |         GOTO Restart               |     END SELECT                   −+   LOOP FUNCTION e (x, y)   '  Line is  y=2                 −+焦点と準線は左のよう   dPL = y + 2                     |に固定してみた。   '  Point is (0,4)                  |実質的には問題はない   dPP = SQR((x) ^ 2 + (y - 4) ^ 2)         |   e = dPP / dPL                    |                             −+ END FUNCTION (4) 観察から「次にしたいこと」は見つかったか?  さて,プログラムを写すだけじゃだめです。これを実行して分かることから,次に何を してみたいと思いましたか。  例えば,「e」の値に対して,もっと「きっちり」とした曲線を求めたいという人もい るでしょう。そういう人は,陰関数のときの工夫を「移植」してみましょう。  あるいは,「離心率」の定義をいろいろと変えてみるとどんな曲線が出来るのかを調べ てみるというのも一つの手かもしれません。そういう場合には,関数eの内容を変えてみ ることになります。  さて,他には面白いテーマはないでしょうか。問題を発見するためには,「固い頭」じ ゃいけません。柔軟な発想が必要です。そして,            「冷かし半分」あるいは「面白半分」 というようなユーモアのセンスに似たものが不可欠です。そして,         脈がありそうなことが見つかったらとことん追究する             脈がなければすぐに見切りをつける というような,文字通りの「山師」(知っているかなあ,こんな死語)的な性格が,とっ ても重要になってくるわけです。

15−5 「例題II」について考える

 さて,こちらの問題の方は,やりたいことはかなり明確ですよね。しかし,最初から一 遍にやりたいところまで到達しようなんて考えると,結構しんどいわけで,              「できることから少しずつ」 という方針の方がいいと思います。そして,そのときに,           「可能ならばより一般的な記述を試みる」 ということをしていくと,必ずしも最初の問題だけにしか通用しないプログラムに拘泥す ることなく,より一般的な場合についても使えるプログラムを作りだすことができるよう になっていきます。  ここでは,プログラムの側から観察していくことにしましょう。 (1) まずは,放物線を描く   COMMON SHARED MaxOfX, MaxOfY, dp   SCREEN 12   MaxOfX = 15   DIM a(2)   a(0) = 1   a(1) = 1   a(2) = 1   CLS   MaxOfY = MaxOfX * 480 / 640   dp = MaxOfX / 320   WINDOW (-MaxOfX, MaxOfY)-(MaxOfX, -MaxOfY)   CALL DrawPoly(a())   END SUB DrawPoly (a())   FOR x = -MaxOfX TO MaxOfX STEP dp / 2     y = ValOfPoly(a(), x)     PSET (x, y)   NEXT END SUB FUNCTION ValOfPoly (a(), x)      FOR i = 0 TO UBOUND(a)        y = y + a(i) * x ^ i      NEXT ValOfPoly = y END FUNCTION  最初から「なんだよ, これ」と思わせるようなプログラムになっちゃいましたね。もち ろん,放物線を描くだけだったら,もっと簡単でいいんだけど,ある程度プロシージャを 意識したかったので,上記の下線部,つまり     CALL DrawPoly(a())  と書きたかったんです。こうしなくても,     CALL Draw2(a,b,c)  とやって, SUB Draw2(a,b,c)   FOR x = -MaxOfX TO MaxOfX STEP dp / 2     y = a * x ^2 + b * x + c     PSET (x, y)   NEXT END SUB  とやる手もあります。しかし,それでは,3次関数について調べるときには,Draw3 を 作る必要があります。同様に,Draw4,Draw5,... が必要です。そこで,       「任意の多項式についてそれを計算する手はないだろうか」 ということを考えて,上記のようにしたわけです。どんな工夫がしてあるか,分析してみ てください。 (2) 直線も追加し,少し見栄えをよくする。  直線も1次関数ですから,多項式。ということは,次のようにできますね。 DECLARE SUB DrawPoly (a!()) DECLARE FUNCTION ValOfPoly! (a!(), x!)   COMMON SHARED MaxOfX, MaxOfY, dp   SCREEN 12   MaxOfX = 15   DIM a(2)   a(0) = 1   a(1) = 1   a(2) = 1   DO     CLS     MaxOfY = MaxOfX * 480 / 640     dp = MaxOfX / 320     WINDOW (-MaxOfX, MaxOfY)-(MaxOfX, -MaxOfY)     LINE (-MaxOfX, 0)-(MaxOfX, 0)     FOR i = -INT(MaxOfX) TO INT(MaxOfX)       LINE (i, 5 * dp)-(i, -5 * dp)     NEXT     LINE (0, -MaxOfY)-(0, MaxOfY)     FOR i = -INT(MaxOfY) TO INT(MaxOfY)       LINE (5 * dp, i)-(-5 * dp, i)     NEXT     CALL DrawPoly(a())     FOR b = -5 TO 5       b(1) = 3       b(0) = b       CALL DrawPoly(b())     NEXT Restart:     LOCATE 1, 1     PRINT "M:MaxOfX, Q:Quit"     a$ = UCASE$(INPUT$(1))     SELECT CASE a$       CASE "M"         INPUT "MaxOfX"; MaxOfX         IF MaxOfX <= 0 THEN MaxOfX = 10       CASE "Q": EXIT DO       CASE ELSE         BEEP         GOTO Restart     END SELECT   LOOP SUB DrawPoly (a())   FOR x = -MaxOfX TO MaxOfX STEP dp / 2     y = ValOfPoly(a(), x)     PSET (x, y)   NEXT END SUB SUB PointOut (x, y)   LINE (x - 5 * dp, y + 5 * dp)-(x + 5 * dp, y - 5 * dp)   LINE (x - 5 * dp, y - 5 * dp)-(x + 5 * dp, y + 5 * dp) END SUB FUNCTION ValOfPoly (a(), x)      FOR i = 0 TO UBOUND(a)        y = y + a(i) * x ^ i      NEXT ValOfPoly = y END FUNCTION (3) 「直線」はちょっと別のSUB を用意した方がいいみたい。  使ってみると,そう「遅い」よね。「汎用」という部分はいいけれど,次のように修正 しようね。   COMMON SHARED MaxOfX, MaxOfY, dp   SCREEN 12   MaxOfX = 15   DIM a(2)   a(0) = 1   a(1) = 1   a(2) = 1   DO     CLS     MaxOfY = MaxOfX * 480 / 640     dp = MaxOfX / 320     WINDOW (-MaxOfX, MaxOfY)-(MaxOfX, -MaxOfY)     LINE (-MaxOfX, 0)-(MaxOfX, 0)     FOR i = -INT(MaxOfX) TO INT(MaxOfX)       LINE (i, 5 * dp)-(i, -5 * dp)     NEXT     LINE (0, -MaxOfY)-(0, MaxOfY)     FOR i = -INT(MaxOfY) TO INT(MaxOfY)       LINE (5 * dp, i)-(-5 * dp, i)     NEXT     CALL DrawPoly(a())     FOR b = -5 TO 5 STEP 2       b(1) = 3       b(0) = b       CALL DrawLine(b())     NEXT Restart:     LOCATE 1, 1     PRINT "M:MaxOfX, Q:Quit"     a$ = UCASE$(INPUT$(1))     SELECT CASE a$       CASE "M"         INPUT "MaxOfX"; MaxOfX         IF MaxOfX <= 0 THEN MaxOfX = 10       CASE "Q": EXIT DO       CASE ELSE         BEEP         GOTO Restart     END SELECT   LOOP SUB DrawLine (a())   x1 = MaxOfX   y1 = a(1) * x1 + a(0)   x2 = -MaxOfX   y2 = a(1) * x2 + a(0)   LINE (x1, y1)-(x2, y2) END SUB SUB DrawPoly (a())   FOR x = -MaxOfX TO MaxOfX STEP dp / 2     y = ValOfPoly(a(), x)     PSET (x, y)   NEXT END SUB SUB PointOut (x, y)   LINE (x - 5 * dp, y + 5 * dp)-(x + 5 * dp, y - 5 * dp)   LINE (x - 5 * dp, y - 5 * dp)-(x + 5 * dp, y + 5 * dp) END SUB FUNCTION ValOfPoly (a(), x)      FOR i = 0 TO UBOUND(a)        y = y + a(i) * x ^ i      NEXT ValOfPoly = y END FUNCTION (4) 交点や中点も描こう  しかし,これでも,「中点」なんかがどこにあるのかは分からない。ちょっと大変だけ ど,いくつかのSUB を追加して,何とかそれを実現しよう。   COMMON SHARED MaxOfX, MaxOfY, dp   SCREEN 12   MaxOfX = 15   DIM a(2), b(1), x(2), y(2)   a(0) = 1   a(1) = 1   a(2) = 1   DO     CLS     MaxOfY = MaxOfX * 480 / 640     dp = MaxOfX / 320     WINDOW (-MaxOfX, MaxOfY)-(MaxOfX, -MaxOfY)     LINE (-MaxOfX, 0)-(MaxOfX, 0)     FOR i = -INT(MaxOfX) TO INT(MaxOfX)       LINE (i, 5 * dp)-(i, -5 * dp)     NEXT     LINE (0, -MaxOfY)-(0, MaxOfY)     FOR i = -INT(MaxOfY) TO INT(MaxOfY)       LINE (5 * dp, i)-(-5 * dp, i)     NEXT     CALL DrawPoly(a())     FOR b = -5 TO 5 STEP 2       b(1) = 3       b(0) = b       CALL DrawLine(b())       CALL GetCrossPoint21(a(), b(), x(), y(), check)       IF check = -1 THEN         CALL PointOut(x(1), y(1), 7)         CALL PointOut(x(2), y(2), 7)         CALL PointOut((x(1) + x(2)) / 2, (y(1) + y(2)) / 2, 7)       END IF     NEXT Restart:     LOCATE 1, 1     PRINT "M:MaxOfX, Q:Quit"     a$ = UCASE$(INPUT$(1))     SELECT CASE a$       CASE "M"         INPUT "MaxOfX"; MaxOfX         IF MaxOfX <= 0 THEN MaxOfX = 10       CASE "Q": EXIT DO       CASE ELSE         BEEP         GOTO Restart     END SELECT   LOOP SUB DrawLine (a())   x1 = MaxOfX   y1 = a(1) * x1 + a(0)   x2 = -MaxOfX   y2 = a(1) * x2 + a(0)   LINE (x1, y1)-(x2, y2) END SUB SUB DrawPoly (a())   FOR x = -MaxOfX TO MaxOfX STEP dp / 2     y = ValOfPoly(a(), x)     PSET (x, y)   NEXT END SUB SUB GetCrossPoint21 (a(), b(), x(), y(), check)   DIM c(2)   c(2) = a(2)   c(1) = a(1) - b(1)   c(0) = a(0) - b(0)   CALL Solve2(c(), x(), check)   IF check = 0 THEN EXIT SUB   y(1) = ValOfPoly(a(), x(1))   y(2) = ValOfPoly(a(), x(2)) END SUB SUB PointOut (x, y, clr)   LINE (x - 5 * dp, y + 5 * dp)-(x + 5 * dp, y - 5 * dp), clr   LINE (x - 5 * dp, y - 5 * dp)-(x + 5 * dp, y + 5 * dp), clr END SUB SUB Solve2 (a(), x(), check)   d = a(1) ^ 2 - 4 * a(2) * a(0)   IF d < 0 THEN     check = 0     EXIT SUB   END IF   x(1) = (-a(1) + SQR(d)) / (2 * a(2))   x(2) = (-a(1) - SQR(d)) / (2 * a(2))   check = -1 END SUB FUNCTION ValOfPoly (a(), x)      FOR i = 0 TO UBOUND(a)        y = y + a(i) * x ^ i      NEXT ValOfPoly = y END FUNCTION (5) 何が分かった。そして,次に何を考えてみたい。  そう,今度も,「見てるだけじゃだめ」なんで,                「だからなんなの」  この後は,自分で考えようね。 +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+ |                                      | | というような調子で,自分なりに取り組んでみたい具体的な課題を考えよう。  | |                                      | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+