2010-05-25 175 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.这很快且容易实现。