This library is a relatively small (<500 cloc) mathematical expression evaluator library written in Nim.
The implementation is a simple recursive-descent evaluator.
It only depends on the stdlib (mostly on the math module), and works on all official Nim backends including JavaScript and in the VM
There's a lot of predefined math functions and some constants, and of course you can define custom ones.
Most of the library usage can be shown in this code example:
import mathexpr # Create a new evaluator instance # All custom variables and math functions are bound to this evaluator # so you could have different evaluators with different vars/functions let e = newEvaluator() echo e.eval("((4 - 2^3 + 1) * -sqrt(3*3+4*4)) / 2") # 7.5 # Add some variables to our Evaluator object e.addVars({"a": 5.0}) echo e.eval("+5^+3+1.1 + a") # 131.1 # Variables with the same name overwrite the old ones e.addVars({"a": 1.0, "b": 2.0}) echo e.eval("a + b") # 3 # Define our custom function which returns # 25 multiplied by all arguments it got proc myFunc(args: seq[float]): float = result = 25 for arg in args: result *= arg e.addFunc("work", myFunc) echo e.eval("work(1, 2, 3) + 5") # 25*1*2*3 + 5 = 155 # Define a custom function which only accepts two arguments proc test(a: seq[float]): float = a[0] + a[1] e.addFunc("test", test, 2) echo e.eval("test(1, 5)") # 6 # In some places parentheses and commas are optional: echo e.eval("work(1 2 3) + 5") # 155 echo e.eval("sqrt 100 + 5") # 15
eval can return NaN or Inf for some inputs, such as 0/0, or 1/0, see src/tests.nim for more info
What is supported?
Supported operators include +, -, /, *, %, ^, <, >, <=, >=, ==, !=
Implemented mathematical functions:
- abs(x) - the absolute value of x
- acos(x) or arccos(x) - the arccosine (in radians) of x
- asin(x) or arcsin(x) - the arcsine (in radians) of x
- atan(x) or arctan(x) or arctg(x) - the arctangent (in radians) of x
- atan2(x, y) or arctan2(x, y) - the arctangent of the quotient from provided x and y
- ceil(x) - the smallest integer greater than or equal to x
- cos(x) - the cosine of x
- cosh(x) - the hyperbolic cosine of x
- deg(x) - converts x in radians to degrees
- exp(x) - the exponential function of x
- sgn(x) - the sign of x
- sqrt(x) - the square root of x
- sum(x, y, z, ...) - sum of all passed arguments
- fac(x) - the factorial of x
- floor(x) - the largest integer not greater than x
- ln(x) - the natural log of x
- log(x) or log10(x) - the common logarithm (base 10) of x
- log2(x) - the binary logarithm (base 2) of x
- max(x, y, z, ...) - biggest argument from any number of arguments
- min(x, y, z, ...) - smallest argument from any number of arguments
- ncr(x, y) or binom(x, y) - the the number of ways a sample of y elements can be obtained from a larger set of x distinguishable objects where order does not matter and repetitions are not allowed
- npr(x, y) - the number of ways of obtaining an ordered subset of y elements from a set of x elements
- rad(x) - converts x in degrees to radians
- pow(x, y) - the x to the y power
- sin(x) - the sine of x
- sinh(x) - the hyperbolic sine of x
- tg(x) or tan(x) - the tangent of x
- tanh(x) - the hyperbolic tangent of x
Predefined constants
- pi - The circle constant (Ludolph's number)
- tau - The circle constant, equals to 2 * pi
- e - Euler's number
Operators in more detail
Following table shows order of evaluation of various operators, lower the precedence - sooner it shall be evaluated.
Precedence | Operator |
---|---|
1 | Exponentiation ^ |
2 | Unary + and - |
3 | Multiplication/division *, /, % |
4 | Addition/substraction +, - |
5 | Less than/Greater than comparison <, <=, >, >= |
6 | Exact comparison ==, != |
Notes on comparison:
- Comparison operators return a float value, 0.0 for false and 1.0 for true
- Every number in mathexpr is a float. Comparing floats exactly is a bit problematic due to precision, so difference less than 0.0001 makes 2 numbers equal by mathexpr's standards.
Types
MathFunction = proc (args: seq[float]): float
- Type of the procedure definition for custom math functions Source Edit
Procs
proc addFunc(e: Evaluator; name: string; fun: MathFunction; argCount = -1) {. ...raises: [], tags: [], forbids: [].}
-
Adds custom function fun with the name name to the evaluator e which will then be available inside of all following e.eval() calls.
argCount specifies the number of arguments this function is allowed to be called with. If it is -1, the function will be able to be called with one or more arguments, otherwise - only with argCount arguments.
Source Edit proc newEvaluator(): Evaluator {....raises: [], tags: [], forbids: [].}
-
Creates a new evaluator instance for evaluating math expressions
There's no limit on the number of evaluator instances, and all functions and math procedures are local to the current instance
Source Edit proc removeFunc(e: Evaluator; name: string) {....raises: [], tags: [], forbids: [].}
- Removes function with the name name from the evaluator e Source Edit