导数计算器
我有兴趣构建一个导数计算器。我绞尽脑汁想解决这个问题,但始终没有找到正确的解决办法。您可以提示一下如何开始吗?谢谢
对不起!我显然想进行象征性的区分。
假设您有函数 f(x) = x^3 + 2x^2 + x
我想显示导数,在本例中 f'(x) = 3x^2 + 4x + 1
我想实现它在 iPhone 的 Objective-C 中。
I'm interested in building a derivative calculator. I've racked my brains over solving the problem, but I haven't found a right solution at all. May you have a hint how to start? Thanks
I'm sorry! I clearly want to make symbolic differentiation.
Let's say you have the function f(x) = x^3 + 2x^2 + x
I want to display the derivative, in this case f'(x) = 3x^2 + 4x + 1
I'd like to implement it in objective-c for the iPhone.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我假设您正在尝试找到函数的精确导数。 (符号微分)
您需要解析数学表达式并将函数中的各个操作存储在树结构中。
例如,
x + sin²(x)
将存储为+
运算,应用于表达式x
和^< /code>sin(x) 和
2
的(求幂)运算。然后,您可以通过将微分规则应用于每个节点来递归地微分树。例如,
+
节点将变为u' + v'
,*
节点将变为uv' + vu'
。I assume that you're trying to find the exact derivative of a function. (Symbolic differentiation)
You need to parse the mathematical expression and store the individual operations in the function in a tree structure.
For example,
x + sin²(x)
would be stored as a+
operation, applied to the expressionx
and a^
(exponentiation) operation ofsin(x)
and2
.You can then recursively differentiate the tree by applying the rules of differentiation to each node. For example, a
+
node would become theu' + v'
, and a*
node would becomeuv' + vu'
.你需要记住你的微积分。基本上你需要两件事:基本函数的导数表和如何推导复合表达式的规则(例如 d(f + g)/dx = df/dx + dg/dx )。然后采用表达式解析器并递归地转到树的其他部分。 (http://www.sosmath.com/tables/derivative/derivative.html)
you need to remember your calculus. basically you need two things: table of derivatives of basic functions and rules of how to derivate compound expressions (like
d(f + g)/dx = df/dx + dg/dx
). Then take expressions parser and recursively go other the tree. (http://www.sosmath.com/tables/derivative/derivative.html)将字符串解析为 S-expression (尽管这通常是在 Lisp 上下文中进行的) ,您可以用几乎任何语言做等效的事情),最简单的是使用 lex/yacc 或等效函数,然后编写一个递归“派生”函数。在 OCaml 风格的方言中,类似这样:(
如果您不知道 OCaml 语法 -
derive
是双参数递归函数,第一个参数是变量名称,第二个参数在连续行中进行数学计算; 例如,如果此参数是Add(x, y)
形式的结构,则返回由两个字段构建的结构Add
,其值为派生的x
和导出的y
;对于第一个模式中derive
可能接收的参数的其他情况也类似;匹配任何东西”)在此之后,您可能有一些清理功能来整理结果表达式(减少分数等),但这会变得复杂,并且对于推导本身来说不是必需的(即,没有它您得到的仍然是正确的答案)。
完成 s-exp 的转换后,再次使用递归函数将生成的 s-exp 重新转换为字符串形式
Parse your string into an S-expression (even though this is usually taken in Lisp context, you can do an equivalent thing in pretty much any language), easiest with lex/yacc or equivalent, then write a recursive "derive" function. In OCaml-ish dialect, something like this:
(If you don't know OCaml syntax -
derive
is two-parameter recursive function, with first parameter the variable name, and the second being mathched in successive lines; for example, if this parameter is a structure of formAdd(x, y)
, return the structureAdd
built from two fields, with values of derivedx
and derivedy
; and similarly for other cases of whatderive
might receive as a parameter;_
in the first pattern means "match anything")After this you might have some clean-up function to tidy up the resultant expression (reducing fractions etc.) but this gets complicated, and is not necessary for derivation itself (i.e. what you get without it is still a correct answer).
When your transformation of the s-exp is done, reconvert the resultant s-exp into string form, again with a recursive function
SLAks 已经描述了符号微分的过程。我只想添加一些内容:
2 * x
将产生2 + 0*x
。这也可以通过树处理来完成(例如,通过将0 * [...]
转换为0
和[...] + 0
到[...]
等等)SLaks already described the procedure for symbolic differentiation. I'd just like to add a few things:
2 * x
would yield2 + 0*x
. This can also be done by tree processing (e.g. by transforming0 * [...]
to0
and[...] + 0
to[...]
and so on)您想要计算什么类型的导数?如果允许使用正弦、余弦和正切等三角函数,这些函数可能最好存储在表中,而多项式等其他函数可能更容易实现。您是否允许函数有多个输入,例如 f(x,y) 而不仅仅是 f(x)?
我的建议是使用单个变量中的多项式,然后考虑添加三角函数、对数函数、指数函数和其他高级函数来计算导数,这可能更难做到。
For what kinds of operations are you wanting to compute a derivative? If you allow trigonometric functions like sine, cosine and tangent, these are probably best stored in a table while others like polynomials may be much easier to do. Are you allowing for functions to have multiple inputs,e.g. f(x,y) rather than just f(x)?
Polynomials in a single variable would be my suggestion and then consider adding in trigonometric, logarithmic, exponential and other advanced functions to compute derivatives which may be harder to do.
对常见函数(+、-、*、/、^、sin、cos 等)进行符号微分,忽略函数或其导数未定义的区域是很容易的。困难的是事后简化结果,这也许是违反直觉的。
要进行微分,请将运算存储在树中(甚至仅使用波兰表示法),并制作每个基本运算的导数表。然后重复应用链式法则和初等导数,并将常数的导数设置为 0。这是快速且易于实现的。
Symbolic differentiation over common functions (+, -, *, /, ^, sin, cos, etc.) ignoring regions where the function or its derivative is undefined is easy. What's difficult, perhaps counterintuitively, is simplifying the result afterward.
To do the differentiation, store the operations in a tree (or even just in Polish notation) and make a table of the derivative of each of the elementary operations. Then repeatedly apply the chain rule and the elementary derivatives, together with setting the derivative of a constant to 0. This is fast and easy to implement.