我有这个代码来计算衍生物:
(define (diff x expr)
(if (not (list? expr))
(if (equal? x expr) 1 0)
(let ((u (cadr expr)) (v (caddr expr)))
(case (car expr)
((+) (list '+ (diff x u) (diff x v)))
((-) (list '- (diff x u) (diff x v)))
((*) (list '+
(list '* u (diff x v))
(list '* v (diff x u))))
((/) (list ‘div (list '-
(list '* v (diff x u))
(list '* u (diff x v)))
(list '* u v)))
))))
如何简化代数表达式?
代替x + x
显示2x
和
代替x * x
显示x^2
答案 0 :(得分:3)
简化algegraic表达式非常困难,特别是与派生计算相比。简化应该以递归方式完成。您首先简化最内层表达式。不要一次尝试太多。我从最简单的简化开始,例如:
0 + x -> x
0 * x -> 0
1 * x -> x
x ^ 0 -> 1
x ^ 1 -> x
通过加法替换减法,乘以除法
x - y -> x + (-1)*x
x / y -> x ^ (-1)
这可能看起来不是简化,但它会简化您的代码。你总是可以在最后反转这一步。
然后,您使用关联性和可交换性来对术语进行排序。将数值移到左侧,按某个预定义的顺序对变量进行排序(不必按字母顺序排列,但应始终相同)
(x * y) * z -> x * (y * z)
x * 2 -> 2 * x
2 * (x * 3) -> 2 * (3 * x)
简化指数
(x ^ y) ^ z -> x^(y * z)
简化数字部分。
2 * (3 * x) -> 6 * x
2 + (3 + x) -> 5 + x
完成此操作后,您可以考虑收集常用表达式。
答案 1 :(得分:0)
来自this code的PAIP可能会有用。它是Common Lisp,与Scheme非常相似。入口点是simp
函数。
请注意,它也使用this file。
历史记录:相关的PAIP章节是指Macsyma,即20世纪60年代在麻省理工学院开发的计算机代数系统,是Mathematica,Maple(现在的Matlab)和其他工具的基础。
答案 2 :(得分:0)
这是一个开始:
将衍生函数从(define (diff x expr) ...)
更改为(define (simp expr) ...)
。
对于x + x
案例,请执行类似
(case (car expr)
((+) (if (equal u v) ; check for identical subexpressions
`(* ,(simp u) 2) ; if u==v, simplify 2u
`(+ ,(simp u) ,(simp v))))
...)
x * x
案例应该类似。最后,如果您需要进行大量不同的简化,可能需要将if
转换为cond
。
这是一个难以解决的问题,eliben给出的链接值得一看。
答案 3 :(得分:0)
一般问题很难,但是您可以通过产品总和的正常形式获得很长的路,表示为从键(变量名称)到系数的有限映射。这种形式非常适用于线性方程和线性求解,它可以扩展到乘法和幂而不会有太多麻烦。如果你在这个表格上定义“智能构造函数”进行算术运算,你可以得到一些合理的符号区分和方程求解。
这是一个快速的黑客,但我在一些应用程序中使用它。它工作的几个;有几次它还不够好。对于更严肃的事情,你说的是多年的工作。
如果您需要代码示例,可以阅读one of my equation solvers。