新しく発言する EXIT インデックスへ
微分公式から導関数を求める

  微分公式から導関数を求める 山中和義 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

 どの公式を使うかで導関数が簡潔になるかが決まります。


インデックスへ EXIT
新規発言を反映させるにはブラウザの更新ボタンを押してください。