如何用F#对数学公式进行不定积分

【摘要】 如何用F#对数学公式进行不定积分(x^3)-x => (0.25*x^4)-(0.5*x^2)

前面一篇博文,介绍了F#对数学表达式进行求导运算,这里再介绍一下如何用F#对数学表达式求积分。求符号积分比求导要复杂一点,其复杂不在于原理,而在于求导的规则少,而求积分的规则非常多,要想相对全面的涵盖是比较难的。

这里只是探索一个求积分的思路,而不会实现一个功能完备的积分引擎。首先还是定义一个数据类型:

type Expr = 
  | CstF of float
  | Var of string
  | Add of Expr * Expr  // +
  | Sub of Expr * Expr // -
  | Mul of Expr * Expr // *
  | Div of Expr * Expr // / 
  | Pow of Expr * Expr // ^ 
  | Sin of Expr  
  | Cos of Expr  
  | Neg of Expr  

再次,给出一个包含少数积分规则的求积分函数:

let rec intf e  =
    match e with
    |CstF f                -> Mul(CstF f, Var "x")
    |Var x                 -> Mul(CstF 0.5, Pow(Var x,CstF 2.))
    |Add(e1, e2)           -> Add(intf e1, intf e2)
    |Sub(e1, e2)           -> Sub(intf e1, intf e2)
    |Pow(Var x,CstF a)     -> Mul(CstF (1./(a+1.)),Pow(Var x,CstF (a + 1.)))
    |e          -> e 

这里主要就是最后一条,即 x ^ a 求积分为 x^(a+1)/(a+1) 。同样的,给出DSL字符串输出的函数:

let rec printExpr2 e =
    match e with
    | CstF f            -> string f
    | Var x             ->  x 
    | Add(e1 , e2) ->  "(" + (printExpr2 e1) + "+" + (printExpr2 e2) + ")"
    | Sub(e1 , e2) ->  "(" + (printExpr2 e1) + "-" + (printExpr2 e2) + ")"
    | Mul(e1 , e2) ->  "(" + (printExpr2 e1) + "*" + (printExpr2 e2) + ")"
    | Div(e1 , e2) ->  "(" + (printExpr2 e1) + "/" + (printExpr2 e2) + ")"
    | Pow(e1 , e2) ->  "(" + (printExpr2 e1) + "^" + (printExpr2 e2) + ")"
    | Sin(e1) ->  "sin(" + (printExpr2 e1) + ")"
    | Cos(e1) ->  "cos(" + (printExpr2 e1) + ")"
    | Neg(e1) ->  "-(" + (printExpr2 e1) + ")"
    | _          -> failwith "unknown operation";;

最后,计算一下数学公式(x^3)-x的积分值:

let e1 = Sub(Pow(Var "x", CstF 3.0), Var "x");; 
printExpr2 e1 + " => " + printExpr2 (intf e1) ;;  

08.jpg

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享