F#表达式化简

简介: 如果使用过Matlab或者Maple等软件,应该知道这类数学软件的符号计算引擎非常强大,可以进行数学公式的推导,比如可以对数学公式进行化简。当然,实现一个功能完备的化简引擎还是不容易的。这里用F# 实现一个简单的化简函数: ( a + x )+( a - x ) => 2 * a

   如果使用过Matlab或者Maple等软件,应该知道这类数学软件的符号计算引擎非常强大,可以进行数学公式的推导,比如可以对数学公式进行化简。当然,实现一个功能完备的化简引擎还是不容易的。这里用F# 实现一个简单的化简函数。

  首先定义一个表达式数据类型:

typeExpr=|CstFoffloat|Varofstring|AddofExpr*Expr// +|SubofExpr*Expr// -|MulofExpr*Expr// *|DivofExpr*Expr// / 

  其次定义一个化简函数,它是化简规则的具体实现:

(*化简*)
letrecsimplifye=matchewith|CstFf->CstFf|Varx->Varx|Add(CstFa, CstFb) ->CstF (a+b)  
|Add(CstF0., e2) ->simplifye2|Add(e1 , CstF0.) ->simplifye1|Add(e1 , e2) whene1=e2->simplify (Mul(CstF2., simplifye1))
|Add(Mul(CstFa, e1) , Mul(CstFb, e2)) whene1=e2->simplify (Mul(CstF (a+b), simplifye1))
|Add(e1,Sub(a,e2))  whene1=e2->simplifya|Add(Add(a, x1),Sub(b, x2)) whenx1=x2->simplify(Add(simplifya,simplifyb))
|Add(e1, e2) ->Add(simplifye1,simplifye2)
|Mul(CstFa, CstFb) ->CstF (a*b)   
|Mul(CstF0., e2) ->CstF0.|Mul(e1 , CstF0.) ->CstF0.|Mul(CstF1., e2) ->simplifye2|Mul(e1 , CstF1.) ->simplifye1|Mul(e1, e2) ->Mul(simplifye1,simplifye2)
|Sub(CstFa, CstFb)  ->CstF (a-b) 
|Sub(Add(e1,e2),e3) whene1=e3->simplifye2|Sub(Add(e1,e2),e3) whene2=e3->simplifye1|Sub(e1, e2) whene1=e2->CstF0.|Sub(e1, e2) ->Sub(simplifye1,simplifye2)
|Div(CstFa, CstFb)  ->CstF (a/b) 
|Div(CstF0., e2) ->CstF0.|Div(e1, e2) whene1=e2->CstF1.|Div(e1, e2) ->Div(simplifye1,simplifye2)
|_->failwith"unknown operation"

  这个化简函数,返回一个是一个自定义DSL的表达式结构,如Sub(Var "a", Var "x") ,下面再定义一个可以化简和打印出字符串的函数:

letrecsimpe=letres=simplifyematchreswith|CstFf->stringf|Varx->x|Add(e1 , e2) ->"("+ (simpe1) +"+"+ (simpe2) +")"|Sub(e1 , e2) ->"("+ (simpe1) +"-"+ (simpe2) +")"|Mul(e1 , e2) ->"("+ (simpe1) +"*"+ (simpe2) +")"|Div(e1 , e2) ->"("+ (simpe1) +"/"+ (simpe2) +")"|_->failwith"unknown operation";;

最后,再定义一个打印DSL表达式的函数:

letrecprintExpre=matchewith|CstFf->stringf|Varx->x|Add(e1 , e2) ->"("+ (printExpre1) +"+"+ (printExpre2) +")"|Sub(e1 , e2) ->"("+ (printExpre1) +"-"+ (printExpre2) +")"|Mul(e1 , e2) ->"("+ (printExpre1) +"*"+ (printExpre2) +")"|Div(e1 , e2) ->"("+ (printExpre1) +"/"+ (printExpre2) +")"|_->failwith"unknown operation";;

至此,可以测试一下,如何化简数学表达式:

//( a + x ) + ( a - x )lete1=Add(Add(Var"a", Var"x"),Sub(Var"a", Var"x")) 
printExpre1+" => "+simpe1 ;;

0.jpg

相关文章
|
5月前
三元表达式使用
三元表达式使用
52 0
|
5月前
|
测试技术
【动态规划】【字符串】【表达式】2019. 解出数学表达式的学生分数
【动态规划】【字符串】【表达式】2019. 解出数学表达式的学生分数
|
5月前
|
存储 Serverless C语言
『C/C++』Eg3:多项式求值
『C/C++』Eg3:多项式求值
|
5月前
|
Java C++ Python
acwing 3302. 表达式求值
acwing 3302. 表达式求值
|
11月前
三元表达式
三元表达式
33 0
|
人工智能 Shell
if 运算表达式
if 运算表达式
50 1
|
存储 算法
逆波兰表达式:计算包含括号的四则运算表达式
平时我们进行数学计算使用的常见书写方式就是中缀表达式,即每一个运算符号都位于计算数的中间,如下: (1+2)\3 而这对于计算机进行求取结果来说,并不是一个最优的方案。
111 0
|
自然语言处理 索引
一种快速的复杂逻辑表达式求取方法
背景最简单的逻辑表达式求取方法是求取所有每个子表达式的值,然后再带入复杂逻辑表达式依次计算得到最终结果,时间复杂度较高。简单的“或运算”和“与运算”,以短路方式实现,不需要计算所有的子表达式的值,计算效率较高。但是,以“或运算”、“与运算”、“否运算”和“嵌套运算”等子表达式组成的复杂逻辑表达式,不能简单的套用短路运算。本专利,通过“构建逻辑表达式树”及“逐级向上触发树节点”的方式,实现了一种快速
一种快速的复杂逻辑表达式求取方法
|
算法 Java C++
【27. 表达式求值(中缀表达式)】
表达式求值(中缀) **前提准备** 需要开辟`俩个栈`,一个用于`存放数字`,另一个用于`存放运算符`。 需要用到`unordered_map`用来存放`运算符的优先级`。
192 0
【27. 表达式求值(中缀表达式)】
|
存储 人工智能 Serverless
6-2 多项式求值 (15 分)
6-2 多项式求值 (15 分)
137 0