递归区分基本表达式

时间:2017-03-10 05:55:23

标签: algorithm math calculus mathematical-expressions

如果我有一个表达式,例如x * x * x,则存储在如下数据结构中:mult(var x,mult(var x,var x))

我想实现一个函数来递归地区分方程(所以3 * x * x或x * x +(x + x)* x等,不需要简化),任何建议如何成为这个?< / p>

2 个答案:

答案 0 :(得分:2)

您会找到匹配的差异规则并应用它。例如,在这种情况下,我们有规则(其中A和B代表整个子表达式)

var textEdit = new UITextField (new CGRect (15, 100, 200, 30));
textEdit.Enabled = false;

textEdit.Text = "Hello from Xamarin";
var xamImageView = new UIImageView (new CGRect (0,0, 25, 25));
xamImageView.Image = UIImage.FromBundle ("xamagon");
textEdit.RightView = xamImageView;
textEdit.TextAlignment = UITextAlignment.Right;
textEdit.RightViewMode = UITextFieldViewMode.Always;
textEdit.BorderStyle = UITextBorderStyle.None;

此规则的左侧与我们设置

时的公式匹配
diff(mult(A, B)) -> add(mult(diff(A),B), mult(A, diff(B)))

因此我们可以将此规则应用于公式并获取

A = var x
B = mult(var x, var x)

现在对剩余的差异操作进行递归处理。

您需要的另一条规则是:

diff(mult(var x, mult(var x, var x))) ->
  add(mult(diff(var x),mult(var x, var x)), mult(var x, diff(mult(var x, var x))))

答案 1 :(得分:2)

请注意指出语言会有所不同。 Lisp特别适合这个问题。

(defun d (f x)
  (etypecase f
    (number 0)
    (symbol (if (eq f x) 1 0))
    (list (df (first f) (rest f) x))))

(defun df (op args x)
  (let ((a (first args))
        (b (second args)))
    (case op
      ((+ -) `(,op ,(d a x) ,(d b x)))
      (* `(+ (* ,a ,(d b x)) (* ,(d a x) ,b)))
      (/ `(/ (- (* ,(d a x) ,b) (* ,a ,(d b x))) (^ ,b 2)))
      (^ `(* (* ,b (^ ,a ,(1- b))) ,(d a x)))
      (sin `(* (cos ,a) ,(d a x)))
      (cos `(* (- (sin ,a)) ,(d a x))))))

Lisp喜欢前缀表示法。这相当于表达式的抽象语法树。二进制操作看起来像(op lhs rhs)。所以要区分(3 sin(x^2))^2

> (d '(^ (* (sin (^ x 2)) 3) 2) 'x)
(* (* 2 (^ (* (SIN (^ X 2)) 3) 1))
 (+ (* (SIN (^ X 2)) 0) (* (* (COS (^ X 2)) (* (* 2 (^ X 1)) 1)) 3)))

这是一个正确的答案,但显然它远非简单的形式。所以下一步是添加表达式简化器。有一个非常简陋的,

> (simplify (d '(^ (* (sin (^ x 2)) 3) 2) 'x))
(* (* 2 (* (SIN (^ X 2)) 3)) (* (* (COS (^ X 2)) (* 2 X)) 3))

使用中缀表示法,这是2(3 sin(x^2)) (3 cos(x^2) (2x))。显然,可以进行更多的简化,但最简单的是#34;通过任何有用的定义是一个复杂的主题。