golang实现的公式引擎
由于之前开发一个报表系统,需要对数据进行自定义计算,故开发设计了一个数学公式引擎
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 | 2>>1 | 1 |
| << | 2 | 1<<1 | 2 |
1.1 调用方法
- 1.1.1 普通数学公式调用
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 自定义参数调用
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
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 注册自定义函数
func init() { var f opt.Function = new(CustomFunction) err := formula.Register(&f) if err != nil { log.Fatal(err) } }
2.3 调用自定义函数
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 性能测试
BenchmarkOnePlusOne-8 50000 26676 ns/op BenchmarkOne-8 100000 19401 ns/op BenchmarkComplexOne-8 10000 180650 ns/op BenchmarkSin-8 20000 78591 ns/op