微分公式から導関数を求める 山中和義 2007/01/11 23:29:20 ├続き 山中和義 2007/01/11 23:32:28 └初等関数をかっこ付きの四則演算で表現した... 山中和義 2007/01/13 15:07:46 └多重かっこの簡略、関数の定義の変更 山中和義 2007/01/14 17:43:47 └逆ポーランド記法に変換するプログラムがで... 山中和義 2007/01/16 14:09:30
微分公式から導関数を求める 山中和義 2007/01/11 23:29:20 ツリーへ
微分公式から導関数を求める |
返事を書く |
山中和義 2007/01/11 23:29:20 | |
初等関数fを文字列で定義して、その導関数f'を求め、微分の公式(例.(fg)'=f'g+fg')を
使って、f,g,f',g'の部分の文字を置き換えることで実現しています。 四則演算の数式演算処理と組み合わせれば、より実用的になると思います。 !微分の公式を使って数式の導関数を求める ※数式電卓ふ〜 !元の関数 f(x)=A*x^2 LET f$="A" !※+,-,*,/の演算子を含まない LET g$="X^2" LET op$="*" !積の公式 ※+,-,*,/,t,LOG LET f$="X^2" !元の関数 f(x)=x^2+SIN(x) LET g$="SIN(X)" LET op$="+" LET f$="X^2" !元の関数 f(x)=x^2*COS(x) LET g$="COS(X)" LET op$="*" LET f$="EXP(X)" !元の関数 f(x)=EXP(2*x) LET g$="EXP(X)" LET op$="*" LET f$="1" !元の関数 f(x)=1/SIN(x) LET g$="SIN(X)" LET op$="/" LET f$="SIN(X)" !元の関数 f(x)=SIN(x^2) LET g$="X^2" LET op$="t" LET f$="X^2" !元の関数 f(x)=(SIN(x))^2 LET g$="SIN(X)" LET op$="t" LET f$="SIN(X)" !元の関数 f(x)=SIN(A*x) LET g$="A*X" LET op$="t" LET f$="X" !元の関数 f(x)=x^x LET g$="X" LET op$="^" LET f$="X^2" !元の関数 f(x)=x^2*EXP(-x) LET g$="EXP(-X)" LET op$="*" LET d$=diff$(f$,op$,g$) PRINT "導関数=";d$ FUNCTION diff$(f$,op$,g$) !導関数を求める PRINT "f=";f$,"g=";g$ LET df$=dfx$("X",f$) !fの導関数f' LET dg$=dfx$("X",g$) !g' PRINT "f'=";df$,"g'=";dg$ LET d$=dfg$("f",op$,"g") !微分の公式から導関数を求める IF op$="t" THEN !合成関数なら LET p=POS(df$,"X") !y=f(t)、t=g(x) → y=f(g(x)) IF df$(p-1:p+1)="(X)" THEN LET df$(p:p)=g$ ELSE LET df$(p:p)="("&g$&")" END IF END IF LET t$=replace$(d$,"f'",df$) !導関数部分 LET t$=replace$(t$,"g'",dg$) LET t$=replace$(t$,"0*f","0") !整形 LET t$=replace$(t$,"f*0","0") LET t$=replace$(t$,"0*g","0") !整形 LET t$=replace$(t$,"g*0","0") LET t$=replace$(t$,"f",f$) !元の関数部分 LET t$=replace$(t$,"g",g$) LET t$=trim$(t$) !整形 LET t$=replace$(t$,"X^2/X","X") !X^2/X LET t$=replace$(t$,"X/X","1") !X/X LET t$=replace$(t$,"LOG(EXP(1))","1") !LOG(EXP(1)) LET t$=replace$(t$,"LOG(1)","0") !LOG(1)) LET t$=trim$(t$) !整形 LET diff$=t$ END FUNCTION FUNCTION trim$(d$) !0、1を削除する LET t$=replace$(t$,"1*","") !含む"1*1"→"1" LET t$=replace$(t$,"*1","") LET t$=replace$(t$,"1/1","1") LET t$=replace$(t$,"0/1","0") LET t$=replace$(t$,"0+","") LET t$=replace$(t$,"+0","") LET t$=replace$(t$,"0-","-") LET t$=replace$(t$,"-0","") LET t$=replace$(t$,"^1","") LET t$=replace$(t$,"^2^2","^4") LET t$=replace$(t$,"(1)","1") !含む"^(1)"→"^1"→"" LET t$=replace$(t$,"(0)","0") !含む"^(0)"→"^0" LET trim$=t$ END FUNCTION |
├続き 山中和義 2007/01/11 23:32:28 ツリーへ
Re: 微分公式から導関数を求める |
返事を書く |
山中和義 2007/01/11 23:32:28 | |
続き
FUNCTION replace$(d$,f$,t$) !文字列d$の文字f$をt$に置き換える LET dd$=d$ LET p=POS(dd$,f$) !最初から DO WHILE p>0 !存在するなら LET dd$(p:p+LEN(f$)-1)=t$ LET p=POS(dd$,f$,p+LEN(f$)) !次へ LOOP LET replace$=dd$ END FUNCTION FUNCTION dfg$(f$,op$,g$) !微分の公式 SELECT CASE op$ !演算子に応じて CASE "" LET t$=f$&"'" !f' CASE "+","-" LET t$=f$&"'"&op$&g$&"'" !f'±g' CASE "*" LET t$=f$&"'*"&g$&"+"&f$&"*"&g$&"'" !f'*g+f*g' CASE "/" LET t$="("&f$&"'*"&g$&"-"&f$&"*"&g$&"')/"&g$&"^2" !(f'*g-f*g')/g^2 CASE "t" !合成関数f(g) LET t$=f$&"'*"&g$&"'" !f'(g)*g' CASE "LOG" !対数関数log(f) LET t$=f$&"'/"&f$ !f'/f CASE "^" !対数微分 y=x^f、両辺に対数をとるLOG(Y)=f*LOG(X)、y'/y=f'*LOG(X)+f*(1/X) LET t$="X^"&f$&"*("&f$&"'*LOG(X)+"&f$&"/X)" !X^f*(f'*LOG(X)+f*(1/X)) CASE ELSE END SELECT IF op$="" THEN !公式を表示する PRINT "(";f$;")'="; ELSEIF op$="t" THEN PRINT "(";f$;"(t),t=";g$;")'="; ELSEIF op$="LOG" THEN PRINT "(log(";f$;"))'="; ELSE PRINT "(";f$;op$;g$;")'="; END IF PRINT t$ LET dfg$=t$ END FUNCTION FUNCTION dfx$(x$,f$) !初等関数y=f(x)の導関数y'=f'(x) LET t$="?" IF f$="TAN("&x$&")" THEN LET t$="1/COS(X)^2" !三角関数 IF f$="COS("&x$&")" THEN LET t$="(-SIN(X))" IF f$="SIN("&x$&")" THEN LET t$="COS(X)" IF f$="ATN("&x$&")" THEN LET t$="1/(1+X^2)" IF f$="EXP("&x$&")" THEN LET t$="EXP(X)" !指数関数 IF f$="EXP(-"&x$&")" THEN LET t$="(-EXP(-X))" IF f$="A^"&x$ THEN LET t$="A^X*LOG(A)" IF f$="LOG("&x$&")" THEN LET t$="1/X" !対数関数 IF f$="LOGa("&x$&")" THEN LET t$="1/(X*LOG(A))" IF f$="LOG(A*"&x$&")" THEN LET t$="1/X" !log(AX)=log(A)+log(X) IF f$=x$&"^n" THEN LET t$="n*X^(n-1)" !べき関数 IF f$=x$&"^4" OR f$=x$&"*"&x$&"*"&x$&"*"&x$ THEN LET t$="4*X^3" IF f$=x$&"^3" OR f$=x$&"*"&x$&"*"&x$ THEN LET t$="3*X^2" IF f$=x$&"^2" OR f$=x$&"*"&x$ THEN LET t$="2*X" IF f$=x$&"^1" OR f$=x$ THEN LET t$="1" IF f$=x$&"^(1/2)" OR f$="SQR("&x$&")" THEN LET t$="1/(2*SQR(X))" !平方根 IF f$=x$&"^0" THEN LET t$="0" IF f$="1/"&x$ OR f$=x$&"^(-1)" THEN LET t$="(-1/X^2)" !1/x IF f$="A*"&x$ THEN LET t$="A" !A*X IF f$="-"&x$ OR f$="(-1)*"&x$ THEN LET t$="(-1)" !(-1)*X IF f$="2*"&x$ THEN LET t$="2" !2*X IF f$="3*"&x$ THEN LET t$="3" !3*X IF f$="4*"&x$ THEN LET t$="4" !4*X IF f$="1" THEN LET t$="0" !定数 IF f$="A" THEN LET t$="0" LET dfx$=t$ END FUNCTION END |
└初等関数をかっこ付きの四則演算で表現した... 山中和義 2007/01/13 15:07:46 ツリーへ
Re: 微分公式から導関数を求める |
返事を書く |
山中和義 2007/01/13 15:07:46 | |
初等関数をかっこ付きの四則演算で表現した関数f(x)の導関数f'(x)を求める。
●関数の定義 関数::= <項> { { + | - } <項> }* 項::= <因子> { { * | / } <因子> }* 因子::= <初等関数> | ( <関数> ) 初等関数::= SIN(X) | COS(X) | TAN(X) | ATN(X) //三角関数 | EXP(X) //指数関数 | LOG(X) //対数関数 | X | X^<関数> //べき乗 | <数値> | <文字> //定数 <数値>::={ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 }* <文字>::={ A | B | C | D | E | K | L | M | N } //※関数、変数に使う文字を除く | いずれか1つ * 0回以上の繰り返し ●処理手順 ・関数を文字列で得る。 例 関数f(x)=2*x+sin(x) → 2*X+SIN(X) ・逆ポーランド記法に変換する 関数を逆ポーランド記法の文字列に変換する。 例 2*X+SIN(X) → 2 X * SIN(X) + ・スタック計算機で計算する 逆ポーランド記法の文字列を、スタック操作(push/pop)で逐次計算していく。 四則演算に微分の公式を摘要して(文字列の置き換え)、導関数の文字列を得る。 例 演算子*で、関数とその導関数をスタックに積む。 2 X * → push(s) (2 X *)' → 2'*X+2*X' ※(fg)'=f'g+fg' → 2 → push(s') 演算子+で、関数とその導関数をスタックに積む。累積される。 pop(s) SIN(X) + → push(s) (pop(s) SIN(X) +)' → pop(s')+COS(X) ※(f+g)'=f'+g' → push(s') 最終的に pop(s) → 関数f(x) pop(s') → 導関数f'(x) ●式の整理 次に注意して求めた導関数を簡潔に記述する。 ・0をたす、0をひく、0をかける、べき乗0、1をかける、1で割る、べき乗1 ・2重かっこ ・約分 ・展開、同類項、因数分解 試作 スタック計算機で計算する http://www.urban.ne.jp/home/kz4ymnk/seminar/basic/diff.html |
└多重かっこの簡略、関数の定義の変更 山中和義 2007/01/14 17:43:47 ツリーへ
Re: 初等関数をかっこ付きの四則演算で表現した... |
返事を書く |
山中和義 2007/01/14 17:43:47 | |
多重かっこの簡略、関数の定義の変更
かっこ({}、[]、())を使って、生成規則を観察しました。 文字列の置き換えで何とかなるようです。 関数の定義(BNF) 関数::= F( <変数> )= <式> 式::= <項> { { + | - } <項> }* 項::= <因子> { { * | / } <因子> }* 因子::= { <初等関数> | ( <式> ) } { ^ { <初等関数> | ( <式> ) } }* //べき乗 初等関数::= SIN( <式> ) | COS( <式> ) | TAN( <式> ) | ATN( <式> ) //三角関数 | EXP( <式> ) //指数関数 | LOG( <式> ) //対数関数 | SQR( <式> ) | <数値> | <文字> //定数 | <変数> <数値>::= { 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 }+ <文字>::= { A | B | C | D | E | K | L | M | N } //※関数名、変数名に使う文字を除く <変数>::= X {} グループ化 | あるいは(OR) * 0回以上の繰り返し + 1回以上の繰り返し 次は、数式を逆ポーランド記法に変換するプログラムを作らないと、、、 試作 スタック計算機で計算する http://www.urban.ne.jp/home/kz4ymnk/seminar/basic/diff.html |
└逆ポーランド記法に変換するプログラムがで... 山中和義 2007/01/16 14:09:30 ツリーへ
Re: 多重かっこの簡略、関数の定義の変更 |
返事を書く |
山中和義 2007/01/16 14:09:30 | |
逆ポーランド記法に変換するプログラムができました。
関数の定義などを変更しています。BNFをそのままコーディングしてみました。 次は、フロントエンド、バックエンドプロセッサとして連動動作できるように モジュールのすり合わせが必要です、、、 言語処理系 数式を逆ポーランド記法に変換する http://www.urban.ne.jp/home/kz4ymnk/seminar/basic/e2rpn.html 逆ポーランド記法の数式を計算する http://www.urban.ne.jp/home/kz4ymnk/seminar/basic/calc_rpn.html 試作 導関数を求める(元の関数は逆ポーランド記法の数式) http://www.urban.ne.jp/home/kz4ymnk/seminar/basic/diff.html どの公式を使うかで導関数が簡潔になるかが決まります。 |