定積分:対数関数

曲線とx軸、x=a,x=b で囲まれた部分をインタラクティブに変えながら定積分の値を表示します。

教材として見せ、適当な状態の図をTeXの図に書き出すことにします。

関数は y=log x を例にとります。次の図です。

まず、画面設計です。

(1) y=log x のグラフを表示する。

(2) y軸に平行な直線 x=a , x=b をとり、これをインタラクティブに動かす。

(3) 積分の式とその値を表示する。

(1) はPlotdata()を使いましょう。

(2) y軸に平行な直線 x=a , x=b は、点を4つとり、2つはx軸上のx>0の部分を動くようにし、あとの2つはそれに対応して曲線上に乗るようにします。縦の線分はKETCindyのLineplot()で書けばよいでしょう。

では、まず作図ツールで必要な点と線をとります。

点を4つとりますが、2つはx軸上を動くようにするので、先にx軸をとりましょう。

スナップツール(磁石アイコン)で軸と方眼を表示しておき、直線を加えるツールでx軸上に直線を引きます。

次に、2つの点をx軸上に置き、あとの2つの点は他の適当なところにとっておきます。

はじめにとった2つの点がx軸上だけを動くことを確かめておきましょう。もし外れるようなら、「点の取り付け/取り外し」ツールを使って直線上に乗せます。

次にスクリプトを書きます。

Plotdata("1","log(x)","x=[0.01,10]",["Num=200"]);

E.xy=[C.x,log(C.x)];

F.xy=[D.x,log(D.x)];

Listplot([C,E]);

Listplot([F,D]);

これで、グラフが描かれ、点E,Fはグラフ上に乗ります。点C,Dをドラッグして動かすので、インスペクタを用いて色を変えておきましょう。

コンソールを見ると3つのプロットデータ gr1 , sgCE ,sgFD が作られたことがわかるでしょう。

次に、x軸とグラフで挟まれた部分にShade()で色を塗ります。そのためには、線分CDのプロットデータと、E,F間の部分曲線のデータが必要になります。

Listplot([D,C]);

Partcrv("1",E,F,"gr1");

ここで、線分CDを [C,D] ではなく [D,C] としているのは、領域をぐるっとまわる順番を意識しているからです。

C -> E -> F -> D -> C

という順序です。先ほど、線分DFを描くのに、[F,D]としたのも実はこの理由です。

これでプロットデータ sgDC と part1 ができます。これらのプロットデータを使ってShadeで色を塗ります。

Shade(["sgCE","part1","sgFD","sgDC"],[0.1,"color->[0,1,0],alpha->0.7"]);

TeXに書き出すと次のようになります。

では、これに必要な数字と、定積分の式をいれます。

数字は、軸上の点の座標ですが、これは Letter([位置, 方向, 文字列]) を用います。

定積分の式は、Expr([座標, 位置, 文字列]) で書き、計算は integrate(関数式, 変数, 範囲, option) を使います。

if(C.x<1,derec="n2",derec="s2");

Letter([C,derec,"a",[1,0],"s2","1",D,"s2","b"]);

Expr([1,3],"e","\displaystyle \int_a^b \log x\,dx {\doteqdot}"+text(Integrate("log(x)","x",[C.x,D.x],"s")));

Expr([1,2.5],"se2","(a="+text(C.x)+",\; b="+text(D.x)+")");

ここで、1行目と2行目は、数字が領域の区切り線と重ならないように、点Cが1より左のときは座標軸の上に数字を入れるための工夫です。

点Dが1より小さいときも考えるならば、点Dについても同じ処理が必要です。

これで次の図(冒頭の図)ができました。

さらに工夫を

これでひとまずできたのですが、ちょっと問題があります。それから、工夫したい点もあります。

まず、問題点ですが、点Cをドラッグして積分範囲を変えるとき、いったん 1 で止まると、次にその点を動かすことができなくなってしまうのです。その理由は、点Cと点Eが(1,0)で重なってしまうからです。点Cを選択しようとすると、点Eも同時に選択されてしまうのです。2つの点は同時には動かせません。

もうひとつ、定義域は正なので、点Cがマイナスの方へ動かないようにしたいのです。

次に、工夫ですが、x軸より上は定積分の値が正、下は負になるので、軸の上下で色分けをして示しましょう。TeXの文書ではモノクロにするならその必要はないのですが、授業でやってみせるにはその方がよいでしょう。

まず、問題点から。点Cをドラッグするとこのようなことが起こります。そこで、別のスライダを作って、C,D,E,Fの位置を決めることにします。

スライダは定義域に合わせて正の部分だけ作ればよいでしょう。y=-2 の正の部分です。

スライダの端点がG, スライダ上の点がK,Lであるとして、次のスクリプトを先頭部分に加えて実行してみます。

G.x=0.01;

C.x=K.x;

D.x=L.x;

KとLのドラッグでC,D,E,Fが動くようになればOKです。

もうひとつ。スライダ上の点が端点Gに来てしまった場合のことを考えて、インスペクタで点Gを「ピンで留める」にしておきます。

(「ピンで留める」にしたら、スクリプトの G.x=0.01 は削除しても構いません)

色や大きさもそれぞれ変えておきましょう。

次に、x軸の上下での色変えです。

3つの場合があります。

(1) C,Dとも1より左

(2) Cは1の左、Dは右

(3) C,Dとも1の右

(1)と(3)は先ほどと同じで色を変えるだけです。(2)が問題です。2つに分けなければいけません。

そこで、(1,0) に点Mを置いて、EM,MFの部分曲線を追加します。線分MC,DM も必要です。(ひとまわりする向きも考えています)

プロットデータが追加できたら、if関数で場合分けして色を塗ります。

Listplot([M,C]);

Listplot([D,M]);

Partcrv("2",E,M,"gr1");

Partcrv("3",M,F,"gr1");

if(K.x<1 & L.x<1,

Shade(["sgCE","part1","sgFD","sgDC"],[0.1,"color->[1,1,0],alpha->0.7"]);

);

if(K.x<1 & 1<=L.x,

Shade(["sgCE","part2","sgMC"],[0.5,"color->[1,1,0],alpha->0.7"]);

Shade(["part3","sgFD","sgDM"],[0.5,"color->[0,1,0],alpha->0.7"]);

);

if(1<=K.x & 1<=L.x,

Shade(["sgCE","part1","sgFD","sgDC"],[0.1,"color->[0,1,0],alpha->0.7"]);

);

TeXに書き出される図は以前と同じです。

こんな方法もあります

TeXの図をモノクロにするのなら、C,D の位置による場合分けは不要です。

初めに書いた Shade(・・) だけでどの場合も書けます。

今やったのは画面上で色分けするためのものです。

ところで、TeXの図に出力するのはKETCindyのコマンドです。

それなら、Cindyscriptだけで色分けはできないでしょうか。

実は、Cindyscript でfillpoly() を使えばもっと簡単にできるのです。

ただし、次のことを理解しておく必要があります。

Plotdata() で描いたグラフのプロットデータは、グラフ上の点のリストである

つまり、中学生がグラフを描くように、点をたくさんとっておいて結んでいるのです。オプションの ["Num=200"]はその点を200個とることを意味しています。

一方、Cindyscript のfillpoly()関数は、点のリストを与えて色塗り多角形を作る関数です。

それなら、プロットデータがそのまま使えるではありませんか。

ただし、上の黄色の部分の場合、[C,E,part2] とやると、part2そのものが点のリストなので、リストがネスティングされることになります。

そこで、リストを平滑化する関数を使って、ネスティングを解消してやります。

この方法なら、線分CM,MDを引く必要はありません。fillpoly()が自動的に閉じてくれるからです。

Shade(["sgCE","part1","sgFD","sgDC"],[0.1,"color->[1,1,0],alpha->0.7"]);

Partcrv("2",E,M,"gr1");

Partcrv("3",M,F,"gr1");

if(K.x<1 & L.x<1,

fillpoly(flatten([C,part1,D]),color->[1,1,0],alpha->0.7);

);

if(K.x<1 & 1<=L.x,

fillpoly(flatten([C,part2]),color->[1,1,0],alpha->0.7);

fillpoly(flatten([part3,D]),color->[0,1,0],alpha->0.7);

);

if(1<=K.x & 1<=L.x,

fillpoly(flatten([C,part1,D]),color->[0,1,0],alpha->0.7);

);

はじめの Shade(・・)は、最初に書いたものです。すべてをShadeでやるより簡素化されていますね。

さて、最終的に教材として見せるために、全体を少し大きくし、textsize(16); をつけ加えて文字も大きくし、点の名前を非表示にしたのが次の図です。TeXへの出力は変化ありません。

< 戻る >