goJACEgo is a high performance calculation engine for Go, written in pure Go.
'Jace' stands for "Just Another Calculation Engine". it is a port of Jace.NET
goJACEgo can interprete and execute strings containing mathematical formulas. These formulas can rely on variables. If variables are used, values can be provided for these variables at execution time of the mathematical formula.
goJACEgo follows a design similar to most of the modern compilers. Interpretation and execution is done in a number of phases:
During the tokenizing phase, the string is converted into the different kind of tokens: variables, operators and constants.
During the abstract syntax tree creation phase, the tokenized input is converted into a hierarchical tree representing the mathematically formula. This tree unambiguously stores the mathematical calculations that must be executed.
During the optimization phase, the abstract syntax tree is optimized for executing.
More Information: https://pieterderycke.wordpress.com/2012/11/04/jace-net-just-another-calculation-engine-for-net/
goJACEgo can be used in a couple of ways:
To directly execute a given mathematical formula using the provided variables:
engine, _ := gojacego.NewCalculationEngine()
vars := map[string]interface{}{
"a":2,
"b":5
}
result, _ := engine.Calculate("a*b", vars)
// 10.0
To build a Func accepting a map as input containing the values for each variable:
engine, _ := gojacego.NewCalculationEngine(gojacego.WithDecimalSeparator('.'),
gojacego.WithArgumentSeparator(','),
gojacego.WithCaseSensitive(false),
gojacego.WithOptimizeEnabled(true),
gojacego.WithDefaultConstants(true),
gojacego.WithDefaultFunctions(true))
formula := engine.Build("a*b")
vars := map[string]interface{}{
"a":2,
"b":5
}
result, := formula(vars)
// 10.0
The following mathematical operations are supported:
- Addition: +
- Subtraction: -
- Multiplication: *
- Division: /
- Modulo: %
- Exponentiation: ^
The following boolean operations are supported:
- Less than: <
- Less than or equal: <=
- More than: >
- More than or equal: >=
- Equal: ==
- Not Equal: !=
The boolean operations map true to 1.0 and false to 0.0. All functions accepting a condition will consider 0.0 as false and any other value as true.
result, _ := engine.Calculate("5 > 1", nil)
// 1.0
result, _ := engine.Calculate("1E-3*5+2", nil)
// 2.005
vars := map[string]interface{}{
"$a": 1,
"B": 2,
"c_c": 3,
"d1": 4,
"VaR_vAr": 10
}
result, _ := engine.Calculate("$a + B + c_c + d1 + 10 + VaR_vAr", vars)
// 30.0
- Can contains letters ( a-z | A-Z ), underscore ( _ ), dolar sign ( $ ) or a number ( 0-9 ).
- Cannot start with a number.
- Cannot start with underscore.
Constant | Description | More Information |
---|---|---|
e | Euler's number | https://oeis.org/A001113 |
pi | Pi | https://oeis.org/A000796 |
result, _ := engine.Calculate("2*pi", nil)
// 6.283185307179586
The following mathematical functions are out of the box supported:
Function | Arguments | Description | More Information |
---|---|---|---|
sin | sin(x) | Sine | https://pkg.go.dev/math#Sin |
cos | cos(x) | Cosine | https://pkg.go.dev/math#Cos |
asin | asin(x) | Arcsine | https://pkg.go.dev/math#Asin |
acos | acos(x) | Arccosine | https://pkg.go.dev/math#Acos |
tan | tan(x) | Tangent | https://pkg.go.dev/math#Tan |
atan | atan(x) | Arctangent | https://pkg.go.dev/math#Atan |
log | log(x) | Logarithm | https://pkg.go.dev/math#Log |
sqrt | sqrt(x) | Square Root | https://pkg.go.dev/math#Sqrt |
trunc | trunc(x) | Truncate | https://pkg.go.dev/math#Trunc |
floor | floor(x) | Floor | https://pkg.go.dev/math#Floor |
ceil | ceil(x) | Ceil | https://pkg.go.dev/math#Ceil |
round | round(x [,y]) | Round | Rounds a number to a specified number of digits where 'x' is the number and 'y' is the digits. |
random | random(x) | Random | Generate a random double value between 0.0 and 1.0 where 'x' is the seed. |
if | if(a,b,c) | Excel's IF Function | IF 'a' IS true THEN 'b' ELSE 'c'. |
max | max(x1,…,xn) | Maximum | Return the maximum number of a series. |
min | min(x1,…,xn) | Minimum | Return the minimum number of a series. |
// Sin (ordinary function)
vars := map[string]interface{}{
"a":2,
}
ret, _ := engine.Calculate("sin(100)+a", vars)
// 1.4936343588902412
// Round
retRound, _ := engine.Calculate("round(1.234567,2)", nil)
// 1.23
// If
vars := map[string]interface{}{
"a":4,
}
ifresult, _ := engine.Calculate("if(2+2==a, 10, 5)", varsIf)
// 10.0
// MAX
max, _ := engine.Calculate("max(5,6,3,-4,5,3,7,8,13,100)", nil)
// 100.0
Custom functions allow programmers to add additional functions besides the ones already supported (sin, cos, asin, …). Functions are required to have a unique name. The existing functions cannot be overwritten.
engine.AddFunction("addTwo", func(arguments ...interface{}) float64{
return arguments[0] + 2
}, true)
result, _ := engine.Calculate("addTwo(2.0)", nil)
// 4.0
Variables as defined in a formula can be replaced by a constant value at compile time. This feature is useful in case that a number of the parameters don't frequently change and that the formula needs to be executed many times. Thusfore it is better because constants could be optimizated on 'Optimization phase'.
consts := map[string]interface{}{
"a":1,
}
formula := engine.BuildWithConstants("a+b+c", consts)
// It's the same as 'engine.Build("1+b+c")' but without dealing with string replace
vars := map[string]interface{}{
"b":2,
"c":5
}
result, := formula(vars)
// 8.0
https://github.com/mrxrsd/golang-expression-evaluation-comparison
Test | |
---|---|
Benchmark_bexpr-8 | 2278 ns/op |
Benchmark_celgo-8 | 127.0 ns/op |
Benchmark_evalfilter-8 | 1646 ns/op |
Benchmark_expr-8 | 119.1 ns/op |
Benchmark_goja-8 | 306.9 ns/op |
Benchmark_gojacego-8 | 117.3 ns/op |
Benchmark_govaluate-8 | 259.9 ns/op |
Benchmark_gval-8 | 295.0 ns/op |
Benchmark_otto-8 | 951.2 ns/op |
Benchmark_starlark-8 | 5971 ns/op |
Test | Gojacego | Govaluate | Expr | Gval |
---|---|---|---|---|
BenchmarkEvaluationNumericLiteral | 5.42 ns/op | 71.73 ns/op | 87.71 ns/op | 1.89 ns/op |
BenchmarkEvaluationLiteralModifiers | 5.63 ns/op | 180.8 ns/op | 69.92 ns/op | 1.85 ns/op |
BenchmarkEvaluationParameter | 11.25 ns/op | 72.47 ns/op | 69.75 ns/op | 147.1 ns/op |
BenchmarkEvaluationParameters | 31.91 ns/op | 122.0 ns/op | 202.2 ns/op | 315.6 ns/op |
BenchmarkEvaluationParametersModifiers | 56.32 ns/op | 233.3 ns/op | 368.6 ns/op | 378.5 ns/op |
BenchmarkComplexPrecedenceMath | 4.73 ns/op | 18.20 ns/op | 67.96 ns/op | 1.93 ns/op |
BenchmarkMath | 39.22 ns/op | 243.7 ns/op | 252.1 ns/op | 395.3 ns/op |
Disclaimer: GoJACEgo has only mathematical and logical operators while others has more features.