Skip to content

This Go-based math formula parser offers versatile and efficient computation for complex expressions, supporting basic arithmetic, exponentiation, parentheses for grouping, and unique integration of logical if conditions. Users can input formulas that the parser accurately parses and computes.

License

xslasd/mathxf

Repository files navigation

MathXF

license release
这是一个用 Go 语言编写的强大数学计算规则引擎,旨在提供灵活高效的数学表达式计算能力。它支持多种运算符,包括基本的算术运算(如加、减、乘、除)、指数运算、括号分组运算,甚至还包括逻辑条件运算符如 if 语句。该解析器允许用户输入并解析复杂的数学公式,精确计算出表达式的最终结果值。

功能特点:

  1. 全面的运算符支持: 囊括基础算术运算的同时,还融入了指数等高级运算功能。
  2. 条件逻辑集成: 创新性地支持了 if 条件语句,使解析器能够处理含有条件逻辑的数学表达式。
  3. 高度可扩展性: 采用模块化设计,易于扩展,可根据需要轻松添加新的运算符或函数。
  4. 准确性保障: 运用了健壮的解析算法,确保即使是最复杂的公式也能正确解析并计算,同时保持浮点运算的高精度。
  5. 易用性佳: 提供了一套简洁明了、用户友好的API接口,便于无缝集成到各类项目中。

支持操作符:

  1. 算术运算符:+(加法)-(减法)*(乘法)/(除法)%(求余数或模运算)**(幂运算)
  2. 比较运算符:<(小于)>(大于)<=(小于等于)>=(大于等于)==(等于)!= 或 <>(不等于)
  3. 逻辑运算符:&& and(逻辑与)|| or(逻辑或) in (包含)

todo 还没实现 ! not (逻辑非)

支持语法:

  1. if条件判断: if<条件>{ }else if<条件>else{ }
  2. val定义变量:val a;val a,b,c; val a=1;var a,b,c=1
  3. 代码注释: //单行注释; /* */多行注释
  4. 赋值操作: a=1; (常量不能赋值)

支持常量(可动态扩展):

  1. pi=math.Pi
  2. e=math.E

如添加常量ff

	tpl.AddFuncOrConst("ff", 100)

支持函数(可动态扩展):

sum ,avg ,max ,min ,cbrt ,sqrt ,round ,floor ,ceil ,abs ,sin ,cos ,tan ,asin ,acos ,atan ,atan2 ,sinh ,cosh ,tanh ,asinh

函数格式为 func(ctx *mathxf.EvaluatorContext,arg *mathxf.Value)(res1,error)
ctx *EvaluatorContext 可以省略 arg *mathxf.Value 可以多个或使用args ...*mathxf.Value
返回参数必须 1-2个,第2个必须为error

如添加函数 DblEquals

tpl.AddFuncOrConst("DblEquals", func(a, b *mathxf.Value) bool {
  return a.Decimal().Cmp(b.Decimal()) == 0
})

支持模板内容替换:

将显示代码转换成可执行代码

package main
import (
	"fmt"
	"github.com/xslasd/mathxf"
)
func main() {
    input := `
    if 用户显示变量 A > 10 {
      res.aa=5
    }
    `
    tpl, err := mathxf.NewTemplate(input)
    tpl.ReplaceStrMap(map[string]string{
    "用户显示变量 A":"UserA",
    })
    env := map[string]any{
    "UserA":100,
    }
    res, err := tpl.Execute(env)
    if err != nil {
        panic(err)
    }
    for k, v := range res {
        fmt.Printf("--Result.%s---%v\n", k, v)
    }
}

用法

go mod github.com/xslasd/mathxf

  1. mathxf 默认开启精度计算功能,HighPrecision(false) 关闭。精度库使用:github.com/shopspring/decimal
  2. mathxf 计算结果默认放到map[string]map[string]*mathxf.Value中,默认前缀key为”res“,可以使用AddResultKeys(keys ...string)添加返回值前缀Key
  3. mathxf 计算结果map中, 前缀key为"env"中,存放着被修改env值。
  4. mathxf 支持直接计算,但不能和其它语法混用。

直接计算

package main

import (
	"fmt"
	"github.com/xslasd/mathxf"
)

func main() {
	input := `1 + 2 * 6 / 4 + (456 - 8 * 9.2) - (2 + 4 ^ 5)`
	tpl, err := mathxf.NewTemplate(input)
	res, err := tpl.Execute(nil)
	if err != nil {
		panic(err)
	}
	for k, v := range res {
		fmt.Printf("--Result.%s---%v\n", k, v)
	}
}

组合用法

package main

import (
	"fmt"
	"github.com/shopspring/decimal"
	"github.com/xslasd/mathxf"
)

func main() {
	input := `
// 用户优惠劵面值计算规则
if 用户A.总订单数 > 5 && 特价商品区.单价小于10元.订单数<=3 {
   优惠劵面值= 优惠算法((用户A.订单总金额-特价商品区.单价小于10元.订单数*10)*优惠比率最大值,用户A.用户等级)
}
`

	tpl, err := mathxf.NewTemplate(input)
	if err != nil {
		panic(err)
	}
	replaceStrMap := map[string]string{
		"用户A.总订单数":          "TotalOrders",
		"用户A.用户等级":          "UserLevel",
		"用户A.订单总金额":         "OrderTotalAmount",
		"特价商品区.单价小于10元.订单数": "SpecialOffer_10_Orders",
		"优惠比率最大值":           "DiscountRatioMax",
		"优惠劵面值":             "CouponFace",

		"优惠算法": "DiscountAlgorithm",
	}
	tpl.ReplaceStrMap(replaceStrMap)
	tpl.AddFuncOrConst("DiscountAlgorithm", func(a, b *mathxf.Value) decimal.Decimal {
		level := b.Integer()
		if level > 5 {
			return a.Decimal().Mul(decimal.NewFromFloat(0.5))
		} else if level > 3 {
			return a.Decimal().Mul(decimal.NewFromFloat(0.3))
		} else if level >= 1 {
			return a.Decimal().Mul(decimal.NewFromFloat(0.1))
		}
		return decimal.NewFromFloat(0)
	})
	tpl.AddFuncOrConst("DiscountRatioMax", 0.3)
	env := map[string]any{
		"TotalOrders":            10,
		"UserLevel":              1,
		"OrderTotalAmount":       100,
		"SpecialOffer_10_Orders": 3,

		"DiscountRatioMax": 0.3,

		"CouponFace": 0,
	}
	res, err := tpl.Execute(env)
	if err != nil {
		fmt.Println("Execute:", err)
		return
	}
	for k, v := range tpl.PublicValMap() {
		fmt.Printf("--Public.%s---%v\n", k, v.Val)
	}
	for k, v := range res {
		fmt.Printf("--Result.%s---%v\n", k, v)
	}
}

About

This Go-based math formula parser offers versatile and efficient computation for complex expressions, supporting basic arithmetic, exponentiation, parentheses for grouping, and unique integration of logical if conditions. Users can input formulas that the parser accurately parses and computes.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages