golang实现的公式引擎formula

yidane · · 4545 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

> 引言 : > 由于之前开发一个报表系统,需要对数据进行自定义计算,故开发设计了一个数学公式引擎 ## 1、内置函数 支持对数学运算的编译执行,主要支持以下数学公式: * 支持四则运算 * 支持三角函数 * 支持位运算 * 支持三元操作 * 支持自定义参数 * 支持自定义函数 * 支持公式缓存 内置函数如下表 | 函数名称 | 参数个数 | 调用方式 | 结果 | | -------- | -------- | ------------------- | ------------------------ | | abs | 1 | abs(-1) | 1 | | acos | 1 | acos(sqrt(3)/2) | 0.5235987755982991 (π/6) | | asin | 1 | asin(1/2) | 0.5235987755982991 (π/6) | | asin | 1 | asin(1) | π/2 | | atan | 1 | atan(1) | 0.7853981633974483 (π/4) | | ceil | 1 | ceil(3.4) | 4 | | concat | n | concat(1,23,hello) | 123hello | | cos | 1 | cos(π/3) | 0.5000000000000001 | | / | 2 | 3/4 | 0.75 | | exp | 1 | exp(3.3) | 27.112638920657883 | | floor | 1 | floor(2.2) | 2 | | \> | 2 | 3 > 2 | true | | iif | 3 | iif(3 > 2,π,10) | 3.141592653589793 | | \< | 2 | 3 < 2 | false | | in | n | in(3,3,4,5) | true | | ln | 1 | ln(2.718281828) | 0.9999999998311266 | | log2 | 1 | log2(16) | 4 | | log10 | 1 | log10(100000) | 5 | | log | 2 | log(100,10) | 2 | | max | n | max(-1,2,3.1) = 3.1 | 3.1 | | min | n | min(-1,2,3.1) = -1 | -1 | | mod | 2 | mod(5,2) | 1 | | * | 2 | 3*3.4 | 10.2 | | + | 2 | 5+10 | 15 | | pow | 2 | pow(10,2) | 100 | | round | 2 | round(100.11) | 100 | | sign | 1 | sign(100) | false | | sin | 1 | sin(π/6) | 0.49999999999999994 | | - | 2 | 3-6 | -3 | | tan | 1 | tan(π/4) | 1 | | truncate | 1 | truncate(12.3) | 12 | | \>> | 2 | 2>>1 | 1 | | << | 2 | 1<<1 | 2 | ### 1.1 调用方法 * 1.1.1 普通数学公式调用 ``` go expression:=formula.NewExpression("1+2") result,err:=expression.Evaluate() if err!=nil{ //handle err } v,err:= result.Int64() if err!=nil{ //handle err } //v should equal 3 ``` * 1.1.2 自定义参数调用 ```go expression := NewExpression("[i]+[j]") err := expression.AddParameter("i", 1) if err != nil { t.Fatal(err) } err = expression.AddParameter("j", 2) if err != nil { t.Fatal(err) } result, err := expression.Evaluate() //handle result ``` ## 2 自定义公式开发 ### 2.1 实现接口 opt.Function ```go type CustomFunction struct { } func (*CustomFunction) Name() string { return "CustomFunction" } func (f *CustomFunction) Evaluate(context *opt.FormulaContext, args ...*opt.LogicalExpression) (*opt.Argument, error) { err := opt.MatchTwoArgument(f.Name(), args...) if err != nil { return nil, err } left, err := (*args[0]).Evaluate(context) if err != nil { return nil, err } leftValue, err := left.Int64() if err != nil { return nil, err } right, err := (*args[1]).Evaluate(context) if err != nil { return nil, err } rightValue, err := right.Int64() if err != nil { return nil, err } return opt.NewArgumentWithType(leftValue+rightValue+1, reflect.Int64), nil } ``` ### 2.2 注册自定义函数 ```go func init() { var f opt.Function = new(CustomFunction) err := formula.Register(&f) if err != nil { log.Fatal(err) } } ``` ### 2.3 调用自定义函数 ```go expression := formula.NewExpression("CustomFunction(1,2)") result, err := expression.Evaluate() if err != nil { log.Fatal(err) } v, err := result.Int64() if err != nil { log.Fatal(err) } if v != 4 { //CustomFunction: i+j+1 log.Fatal("error") } log.Println("custom function succeed") ``` ## 3 性能测试 ```bash BenchmarkOnePlusOne-8 50000 26676 ns/op BenchmarkOne-8 100000 19401 ns/op BenchmarkComplexOne-8 10000 180650 ns/op BenchmarkSin-8 20000 78591 ns/op ``` ## 4 源码地址 [formula](https://github.com/yidane/formula)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4545 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传