2010-05-25 92 views
4

我對構建衍生產品計算器感興趣。我絞盡腦汁解決問題,但我還沒有找到一個合適的解決方案。可能你有一個提示如何開始?謝謝衍生產品計算器

對不起!我顯然想要做出象徵性的區分。

比方說,你有函數f(x)= X^3 + 2X^2 + X

我想要顯示的衍生,在這種情況下,F'(x)= 3倍^ 2 + 4X + 1

我想在Objective-C中爲iPhone實現它。

+2

你究竟想要做什麼?符號分化? – SLaks 2010-05-25 14:23:58

+3

金融或數學? – 2010-05-25 14:25:49

+0

數值微分是微不足道的。符號絕對是棘手的,但如果你不需要簡化輸出,那麼它很容易實現。 – 2010-05-25 14:44:28

回答

6

我假設你試圖找到函數的確切導數。 (符號區分)

您需要解析數學表達式並將各個操作存儲在樹結構中的函數中。

例如,x + sin²(x)將被存儲爲+操作中,施加到表達xsin(x)2一個^(冪)操作。

然後,您可以通過對每個節點應用區分規則來遞歸地區分樹。例如,+節點將變爲u' + v',並且*節點將變爲uv' + vu'

1

對於您想要計算導數的操作有哪些?如果允許正弦,餘弦和正切等三角函數,這些函數最好存儲在一個表中,而其他類似多項式的函數可能更容易完成。你是否允許函數有多個輸入,例如: f(x,y)而不僅僅是f(x)?

單變量中的多項式是我的建議,然後考慮添加三角函數,對數函數,指數函數和其他高級函數來計算可能難以實現的導數。

+0

只需一個變量f(x)。 – burki 2010-05-26 11:06:42

4

解析你的字符串轉換爲S-expression(即使這通常採取在Lisp的背景下,你可以做一個等價的事情在幾乎任何語言),最簡單的使用lex/yacc的或等效的,然後寫一個遞歸「導出」功能。在OCaml的上下的話,這樣的事情:

let rec derive var = function 
    | Const(_) -> Const(0) 
    | Var(x) -> if x = var then Const(1) else Deriv(Var(x), Var(var)) 
    | Add(x, y) -> Add(derive var x, derive var y) 
    | Mul(a, b) -> Add(Mul(a, derive var b), Mul(derive var a, b)) 
    ... 

(如果你不知道OCaml的語法 - derive有兩個參數遞歸函數,與第一個參數變量名,並在連續行第二被mathched ;在第一_;例如,如果該參數爲形式Add(x, y)的結構,返回由兩場內置結構Add,與衍生x的價值和衍生y;同樣地,對於什麼derive可能會收到作爲參數其他案件圖案意味着「匹配任何東西」)

Afte這可能會有一些清理功能來清理結果表達式(減少分數等)。),但這會變得複雜,而且對於派生本身並不是必需的(即,如果沒有它,它仍然是一個正確的答案)。

當您的S-EXP改造完成後,用遞歸函數

+0

F#太美了 – erikkallen 2010-06-01 19:00:11

2

SLaks已經描述的程序符號微分重新轉換所得的S-EXP成字符串的形式,再次。我只想添加幾件事情:

  • 符號數學主要是解析和樹轉換。 ANTLR是一個很好的工具。我建議從這本好書開始Language implementation patterns
  • 有一些開源軟件可以做你想做的事(例如Maxima)。解剖這樣一個程序也許很有趣(但是如果你試圖自己寫這個程序,可能會更容易理解)
  • 也許你也需要對輸出進行某種簡化。例如,僅將基本派生規則應用於表達式2 * x將產生2 + 0*x。 (例如,通過轉化0 * [...]0[...] + 0[...]等),這也可以通過樹處理完成
1

了常用功能(+,符號微分 - ,*,/,^,正弦,餘弦等)忽略函數或其派生未定義的區域很容易。可能違反直覺的是,後來簡化結果很困難。

爲了進行區分,將操作存儲在樹中(甚至只是用波蘭語表示),並製作每個基本操作的派生表。然後重複應用鏈式法則和基本導數,並將常數的導數設置爲0.這很快且容易實現。