kformula alternatives and similar libraries
Based on the "Misc" category.
Alternatively, view kformula alternatives based on common mentions on social networks and blogs.
-
jclasslib
jclasslib bytecode editor is a tool that visualizes all aspects of compiled Java class files and the contained bytecode. -
kotlin-logging
Lightweight Multiplatform logging framework for Kotlin. A convenient and performant logging facade. -
lingua
The most accurate natural language detection library for Java and the JVM, suitable for long and short text alike -
Kotlift
DISCONTINUED. Kotlift is the first source-to-source language transpiler from Kotlin to Swift -
Humanizer.jvm
Humanizer.jvm meets all your jvm needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities. -
klutter
A mix of random small libraries for Kotlin, the smallest reside here until big enough for their own repository. -
solr-undertow
Solr / SolrCloud running in high performance server - tiny, fast startup, simple to configure, easy deployment without an application server. -
kassava
This library provides some useful kotlin extension functions for implementing toString(), hashCode() and equals() without all of the boilerplate. -
SimpleDNN
SimpleDNN is a machine learning lightweight open-source library written in Kotlin designed to support relevant neural network architectures in natural language processing tasks -
kasechange
🐫🐍🍢🅿 Multiplatform Kotlin library to convert strings between various case formats including Camel Case, Snake Case, Pascal Case and Kebab Case -
kotlin-futures
A collections of extension functions to make the JVM Future, CompletableFuture, ListenableFuture API more functional and Kotlin like. -
PrimeCalendar
PrimeCalendar provides all of the java.util.Calendar functionalities for Persian, Hijri, and ... dates. It is also possible to convert dates to each other. -
log4k
Lightweight logging library for Kotlin/Multiplatform. Supports Android, iOS, JavaScript and plain JVM environments.
CodeRabbit: AI Code Reviews for Developers
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of kformula or a related project?
README
KFormula
[ภาษาไทย](README-th.md)
Mathematical expression engine written in Kotlin, running on JVM.
With KFormula, you can parse simple mathematical expression text and get the evaluated result.
You can add variables/constants, or beyond that, you can define your own function and expose the logic to the engine.
This way you can make your application be able to accept mathematical expression from user's input, or even from database.
If the calculation should be made, simply change the expression to get the new calculation logic apply to your application without recompiling!
Install
Gradle:
repositories {
jcenter()
mavenCentral()
}
dependencies {
...
implementation 'com.github.vittee.kformula:kformula:1.0.3'
...
}
Table Of Contents
Expression
Numeric literal
Only base-10 decimal is supported, no fancy bin/oct/hex/scientific notations.
All values will be stored as BigDecimal
instances.
Percentage numeric literal
KFormula support a special numeric ended with %
sign.
| Literal | Value |
|-----------|-----------|
| 100%
| 1.0 |
| 50%
| 0.5 |
They can be used in percentage operations
Boolean
KFormula operates the expressions as numbers, so true
is 1
, false
is 0
Variable
Variable name must begin with $
or %
sign, followed by any unicode characters and underscores/dots.
Example or valid variable names:
$test |
$2pi |
%discount |
$record.value |
$ตัวแปร |
$変数 |
Variable name that begin with %
sign can be used in percentage operations
Supported operators
Operation | Operator |
---|---|
Add | + |
Subtract | - |
Multiply | * |
Divide | / |
Exponent | ^ |
Modulo | mod |
Logical OR | or |
Logical AND | and |
Logical NOT | not or ! |
Equal | = or == |
Not Equal | != or <> |
Greater than | > |
Less than | < |
Greater than or equal | >= |
Less than or equal | <= |
Special Operators
IN range
Syntax:
<expr> in <begin>...<end>
Returns true
if <expr>
is within the range starting from <begin>
to <end>
It is equivalent to:
(<expr> >= <begin>) and (<expr> <= <end>)
Example:
5 in 5..20
Returns true
20 in 5..20
Returns true
4 in 5..20
Returns false
21 in 5..20
Returns false
NOT IN range
Syntax:
not in <begin>...<end>
!in <begin>...<end>
Returns true
if <expr>
is NOT within the range starting from <begin>
to <end>
It is equivalent to:
(<expr> < <begin>) or (<expr> > <end>)
Example:
5 not in 5..20
5 !in 5..20
Returns false
20 not in 5..20
20 !in 5..20
Returns false
4 not in 5..20
4 !in 5..20
Returns true
21 not in 5..20
21 !in 5..20
Returns true
IN set
Syntax:
<expr> in [<elements>]
Returns true
if <expr>
is a member of the set specified by <elements>
Example:
5 in [5,10,15,20]
Returns true
20 in [5,10,15,20]
Returns true
4 in [5,10,15,20]
Returns false
12 in [5,10,15,20]
Returns false
21 in [5,10,15,20]
Returns false
NOT IN set
Syntax:
not in [<elements>]
!in [<elements>]
Returns true
if <expr>
is NOT a member of a set specified by <elements>
Example:
5 not in [5,10,15,20]
5 !in [5,10,15,20]
Returns false
20 not in [5,10,15,20]
20 !in [5,10,15,20]
Returns false
4 not [5,10,15,20]
4 !in [5,10,15,20]
Returns true
12 not [5,10,15,20]
12 !in [5,10,15,20]
Returns true
21 not [5,10,15,20]
21 !in [5,10,15,20]
Returns true
Ternary
Syntax #1:
if <condition> [then] <true expression> [else <false expression>]
Syntax #2 (function call-like):
IF(<condition>,<true expression>[,<false expression>])
The <true expression>
will be evaluated only if the <condition>
is true
, otherwise <false expression>
will be evaluated (if provided).
If the <false expression>
is omitted and the <condition>
is false
it will return 0
Note: Both the <true expression>
and <false expression>
will be evaluated lazily.
For the syntax #1, then
can be omitted, but not recommended as it would reduce readability.
Example
Assuming that $fee1
is 60
and $fee2
is 30
Syntax #1:
if $weight > 200 then $fee1 else if $weight > 100 then $fee2
Syntax #2:
IF($weight > 200, $fee1, IF($weight > 100, $fee2))
Mixed syntax #1:
IF($weight > 200, $fee1, if $weight > 100 then $fee2)
Mixed syntax #2:
if $weight > 200 then $fee1 else IF($weight > 100, $fee2)
Returns 60
if $weight
is greater than 200
Returns 30
if $weight
is greater than 100
Returns 0
if $weight
is less than or equal 100
Percentage operations
Any variables with name started with %
sign and any numbers that ended with %
sign are considered as percentage values and can be used in adding and subtracting percentage from a value.
Only +
and -
work with right hand side percentage value, e.g:
Expression | Result |
---|---|
30 + 50% | 45 |
400 - 50% | 200 |
120 + %fifty | 180 |
400 - %discount | 300 |
Assuming that %fifty
variable is 0.5
and %discount
is 0.25
Note: Any other operations on percentage values will result in normal arithmetic operations and the result is still percentage value.
Usage
Simple usage
The simplest way is to use Formula
class, it has built-in functions ready for use.
Kotlin:
val code = "1+1"
val fx = Formula()
val program = fx.compile(code)
val result = program.eval()
println("result is $result")
Java:
final String code = "1+1";
final Formula fx = new Formula();
final RootExpr program = fx.compile(code);
final BigDecimal result = program.eval();
System.out.println("result is " + result.toPlainString())
Adding constant
Kotlin:
val fx = Formula().apply {
addConstant("VALUE", 10)
}
Java:
final Formula fx = new Formula();
fx.addConstant("VALUE", 10);
Adding variable
Kotlin:
val fx = Formula().apply {
addVariable("\$test", 300)
addVariable("%fifty", 0.5)
}
Java:
final Formula fx = new Formula();
fx.addVariable("$test", 300);
fx.addVariable("%fifty", 0.5);
Adding external/dynamic variable
It is possible to use a runtime variable in your formula. To do so, you can retreive the runtime variable with a callback function, then use it by "\$external" (Kotlin) or "$external" (Java).
Kotlin:
val fx = Formula().apply {
addExternalVariable("\$external") {
getValue().toBigDecimal()
}
}
Java (with Lambda):
final Formula fx = new Formula();
fx.addExternalVariable("$external", s -> BigDecimal.valueOf(getValue()));
Built-in functions
abs
Returns the absolute value.
Syntax:
abs(value)
Example:
abs(-10)
Returns 10
sum
Returns the sum of all values.
Syntax:
sum(...<values>)
Example:
sum(1,2,3,4,5)
Returns 15
average
Returns the average of all values.
Syntax:
average(...<values>)
Example:
average(1,2,3,4,5)
Returns 3
floor
Returns value rounded down to the nearest integer.
Syntax:
floor(<value>)
Example:
floor(5.321)
Returns 5
ceil
Returns value rounded up to the nearest integer.
Syntax:
ceil(<value>)
Example:
ceil(5.321)
Returns 6
round
Returns value rounded to precision
.
Syntax:
round(<value>, [precision=0])
Example:
round(5.321)
Returns 5
round(5.566)
Returns 6
round(5.566, 1)
Returns 5.6
min
Returns the minimum value.
Syntax:
min(...<values>)
Example:
min(5,1,4,2,3)
Returns 1
max
Returns the maximum value.
Syntax:
max(...<values>)
Example:
max(5,1,4,2,3)
Returns 5
clamp
Clamps the value within the inclusive lower
and upper
bounds.
Syntax:
clamp(<value>, <lower>, <upper>)
Example:
clamp(5, 10, 20)
Returns 5
clamp(25, 10, 20)
Returns 20
clamp(15, 10, 20)
Returns 15
sqrt
Returns the square root of a number.
Syntax:
sqrt(<value>)
Example:
sqrt(9)
Returns 3
sqrt(2)
Returns 1.414213562373095
Adding function
Function can be added to the Formula
instance by calling addFunction
method.
Kotlin addFunction
method definition:
fun addFunction(name: String, vararg signatures: String, handler: FunctionCallHandler)
Java addFunction
method definition:
public void addFunction(String name, String[] signatures, FunctionCallHandler handler)
Function without parameter
Kotlin:
val fx = Formula().apply {
addFunction("one") {
1.toBigDecimal()
}
}
Java (with Lambda):
final Formula fx = new Formula();
fx.addFunction("one", new String[]{}, args -> {
return BigDecimal.valueOf(1);
});
Expression:
one()
Evaluate to 1
one() + one()
Evaluate to 2
Function with parameters
To add a function with parameters, just specify a list of parameter names via the addFunction
method.
The parameter can then be accessed by name via args
parameter in handler.
Kotlin:
val fx = Formula().apply {
addFunction("add", "a", "b") { args ->
args["a"] + args["b"]
}
}
Java (with Lambda):
final Formula fx = new Formula();
fx.addFunction("add", new String[]{"a", "b"}, args -> {
BigDecimal a = args.get("a").eval();
BigDecimal b = args.get("b").eval();
return a.add(b)
});
Example:
add(1,2)
Returns 3
add(1,add(2,4))
Returns 7
Default parameters
Parameters can have default values by specifying parameter names using <name>=<value>
format, e.g. param2=100
Kotlin:
val fx = Formula().apply {
addFunction("add", "a", "b=1") { args ->
args["a"] + args["b"]
}
}
Java (with Lambda):
final Formula fx = new Formula();
fx.addFunction("add", new String[]{"a", "b=1"}, args -> {
BigDecimal a = args.get("a").eval();
BigDecimal b = args.get("b").eval();
return a.add(b)
});
Example:
add(1)
Returns 2
add(1,2)
Returns 3
Variadic parameters
Sometimes, the number of parameters is unknown, you can prefix the parameter name with ...
to make it variadic. (Also known as Rest parameters)
Kotlin:
val fx = Formula().apply {
addFunction("accumulate", "init", "...all") { args ->
val all = args["all"].rest.eval()
args["init"] + all.reduce { sum, v -> sum.add(v) }
}
}
Java (with Lambda):
final Formula fx = new Formula();
fx.addFunction("accumulate", new String[]{"init", "...all"}, args -> {
BigDecimal init = args.get("init").eval();
List<Expr> exprs = args.get("all").getRest();
return exprs.stream().map(Expr::eval).reduce(init, (sum, v) -> sum.add(v));
});
Extending
TBD
*Note that all licence references and agreements mentioned in the kformula README section above
are relevant to that project's source code only.