uCalc Math Parser & Expression Evaluator for C#
Embed Dynamic Formula Evaluation in .NET Applications
If you're looking for a high-performance C# math parser, uCalc is a robust parsing engine you can easily embed in your .NET applications. Beyond standard math evaluators, uCalc enables developers to define custom Domain-Specific Languages (DSLs) at runtime and safely transform structured text.
A minimal example defining a function inline to calculate the area of a rectangle.
ID: 296
using uCalcSoftware;
var uc = new uCalc();
uc.DefineVariable("x = 5");
uc.DefineFunction("Area(length, width) = length * width");
Console.WriteLine(uc.Eval("Area(4, x) + 7"));
27 using uCalcSoftware; var uc = new uCalc(); uc.DefineVariable("x = 5"); uc.DefineFunction("Area(length, width) = length * width"); Console.WriteLine(uc.Eval("Area(4, x) + 7"));
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
uc.DefineVariable("x = 5");
uc.DefineFunction("Area(length, width) = length * width");
cout << uc.Eval("Area(4, x) + 7") << endl;
}
27 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; uc.DefineVariable("x = 5"); uc.DefineFunction("Area(length, width) = length * width"); cout << uc.Eval("Area(4, x) + 7") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
uc.DefineVariable("x = 5")
uc.DefineFunction("Area(length, width) = length * width")
Console.WriteLine(uc.Eval("Area(4, x) + 7"))
End Sub
End Module
27 Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() uc.DefineVariable("x = 5") uc.DefineFunction("Area(length, width) = length * width") Console.WriteLine(uc.Eval("Area(4, x) + 7")) End Sub End Module
Why Choose uCalc as Your C# Math Parser?
Here's How uCalc Compares to the Competition
While tools like NCalc, Flee, and mXParser are great for standard formula evaluation, their grammar is largely fixed. Compiling C# evaluators (like C# Eval Expression) offer immense power but introduce severe security risks if evaluating untrusted user input. Furthermore, high-performance C++ libraries like muParser and ExprTk require complex P/Invoke wrappers to work in .NET.
uCalc provides a completely customizable language workbench that integrates naturally into your C# applications while keeping execution sandboxed.
The Feature Matrix
| Feature | uCalc SDK | NCalc / mXParser | Flee | C# Eval Expression | muParser / ExprTk |
| Runtime Syntax Extensibility | β Yes (Custom operators/functions) | β No (Fixed grammar) | β No (Fixed grammar) | β No (Fixed to C#) | π‘ Limited (Operators are often fixed) |
| Lazy Evaluation (ByExpr) | β Full (Short-circuiting & custom loops) | π‘ Basic Logical Only | β Eager Evaluation | β Supported | β No |
| Integrated Text Transformation | β Token-aware text transformation | β Math-only | β Math-only | β Code-eval only | β Math-only |
| Sandboxed execution | β Configurable Instance Sandbox Β | π’ Safe | π’ Safe | π΄ High Risk (executes arbitrary C#) | π’ Safe |
| C# Integration | β Native Feel | β Native C# | β Native IL Emit | β Native C# | π‘ Requires Wrappers |
Β
Where uCalc Shines vs. Competitors
1. Dynamic Grammar at Runtime (vs. NCalc & mXParser)
If you need a C# math parser to evaluate standard math, most parsers work fine. However, their syntax is unchangeable. uCalc's grammar is fully dynamic. Not only can you can create new functions with DefineFunction(), but using DefineOperator(), you can create prefix, infix, or postfix operators, and configure precedence levels and associativity.Β You can go beyond traditional function and variable definitions and define entirely new literal formats on the fly. You are not just using a math parser; you can build highly readable Domain-Specific Languages (DSLs) tailored to your industry.
2. A Secure Execution Sandbox (vs. C# Eval Expression)
Unlike raw code compilers (such as dynamic Roslyn scripts or C# Eval Expression) where untrusted formulas can execute arbitrary system code, uCalc isolates formula execution inside a controlled engine instance. Host applications retain complete governance over system or file interactions, preventing unauthorized access.
3. Lazy Evaluation & Custom Control Flow (vs. Flee)
Flee is incredibly fast for pure math, but it uses eager evaluationβmeaning all arguments are calculated before a function runs. uCalc introduces advanced argument passing with the ByExpr modifier, enabling true lazy evaluation. Instead of a finalized value, your C# callback receives an unevaluated Expression object. This empowers you to build custom short-circuiting logic, custom conditional statements (like IIf), and custom loops right into the parser.
4. The Token-Aware Transformer (Exclusive to uCalc)
No other C# math parser on the market includes an integrated text restructuring engine. When refactoring code or structured data, standard Regular Expressions are notoriously fragile because they treat everything as a flat stream of characters.
The uCalc Transformer tokenizes text first. It natively understands where strings, nested brackets, and code blocks begin and end, ensuring your find-and-replace rules never accidentally corrupt data. Furthermore, you can execute math logic directly inside your replacement strings using the {@Eval} directive, merging text manipulation with mathematical evaluation in a single step.
5. Non-Throwing Error Architecture (State-Based)
The Competitor Problem: In libraries like NCalc or Flee, syntax errors or invalid user input (e.g., mismatched brackets, division by zero) throw runtime .NET exceptions (
EvaluationException,DivideByZeroException). In interactive apps (dashboards, spreadsheets, form validators), throwing and catching exceptions on every user keystroke causes heavy CLR overhead and clutter.The uCalc Advantage: uCalc uses a state-based error model.
EvalStr()returns user-friendly error messages as clean text strings, and syntax checks can be queried without unwinding the call stack.Β uCalc also supports advanced error handling configurations.
6. Spread-sheet Style Reactive Re-Evaluation (overwrite: true)
The Competitor Problem: In NCalc or mXParser, if Formula A depends on Variable B, updating Variable B requires manually re-evaluating every dependent formula or building an external DAG (Directed Acyclic Graph) dependency engine.
The uCalc Advantage: Setting
overwrite: trueallows new definitions to update dependencies reactively within the parser instance, dramatically simplifying spreadsheet-like and financial modeling engines.
So if you need a powerful C# math parser, then the uCalc SDK has got you covered.
Using the parse-evaluate pattern for high-performance calculations in a loop with a changing variable.
ID: 574
using uCalcSoftware;
var uc = new uCalc();
// Define a variable 'x' that will be updated in the loop.
var variableX = uc.DefineVariable("x");
// Parse the expression just once before the loop begins.
var parsedExpr = uc.Parse("x^2 * 10");
Console.WriteLine("Evaluating 'x^2 * 10' for x = 1 to 5:");
for (double x = 1; x <= 5; x++) {
variableX.Value(x);
// Evaluate is very fast as the parsing work is already done.
Console.WriteLine($"x = {x}, Result = {parsedExpr.Evaluate()}");
}
Evaluating 'x^2 * 10' for x = 1 to 5:
x = 1, Result = 10
x = 2, Result = 40
x = 3, Result = 90
x = 4, Result = 160
x = 5, Result = 250 using uCalcSoftware; var uc = new uCalc(); // Define a variable 'x' that will be updated in the loop. var variableX = uc.DefineVariable("x"); // Parse the expression just once before the loop begins. var parsedExpr = uc.Parse("x^2 * 10"); Console.WriteLine("Evaluating 'x^2 * 10' for x = 1 to 5:"); for (double x = 1; x <= 5; x++) { variableX.Value(x); // Evaluate is very fast as the parsing work is already done. Console.WriteLine($"x = {x}, Result = {parsedExpr.Evaluate()}"); }
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
int main() {
uCalc uc;
// Define a variable 'x' that will be updated in the loop.
auto variableX = uc.DefineVariable("x");
// Parse the expression just once before the loop begins.
auto parsedExpr = uc.Parse("x^2 * 10");
cout << "Evaluating 'x^2 * 10' for x = 1 to 5:" << endl;
for (double x = 1; x <= 5; x++) {
variableX.Value(x);
// Evaluate is very fast as the parsing work is already done.
cout << "x = " << x << ", Result = " << parsedExpr.Evaluate() << endl;
}
}
Evaluating 'x^2 * 10' for x = 1 to 5:
x = 1, Result = 10
x = 2, Result = 40
x = 3, Result = 90
x = 4, Result = 160
x = 5, Result = 250 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; int main() { uCalc uc; // Define a variable 'x' that will be updated in the loop. auto variableX = uc.DefineVariable("x"); // Parse the expression just once before the loop begins. auto parsedExpr = uc.Parse("x^2 * 10"); cout << "Evaluating 'x^2 * 10' for x = 1 to 5:" << endl; for (double x = 1; x <= 5; x++) { variableX.Value(x); // Evaluate is very fast as the parsing work is already done. cout << "x = " << x << ", Result = " << parsedExpr.Evaluate() << endl; } }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub Main()
Dim uc As New uCalc()
'// Define a variable 'x' that will be updated in the loop.
Dim variableX = uc.DefineVariable("x")
'// Parse the expression just once before the loop begins.
Dim parsedExpr = uc.Parse("x^2 * 10")
Console.WriteLine("Evaluating 'x^2 * 10' for x = 1 to 5:")
For x As Double = 1 To 5
variableX.Value(x)
'// Evaluate is very fast as the parsing work is already done.
Console.WriteLine($"x = {x}, Result = {parsedExpr.Evaluate()}")
Next
End Sub
End Module
Evaluating 'x^2 * 10' for x = 1 to 5:
x = 1, Result = 10
x = 2, Result = 40
x = 3, Result = 90
x = 4, Result = 160
x = 5, Result = 250 Imports System Imports uCalcSoftware Public Module Program Public Sub Main() Dim uc As New uCalc() '// Define a variable 'x' that will be updated in the loop. Dim variableX = uc.DefineVariable("x") '// Parse the expression just once before the loop begins. Dim parsedExpr = uc.Parse("x^2 * 10") Console.WriteLine("Evaluating 'x^2 * 10' for x = 1 to 5:") For x As Double = 1 To 5 variableX.Value(x) '// Evaluate is very fast as the parsing work is already done. Console.WriteLine($"x = {x}, Result = {parsedExpr.Evaluate()}") Next End Sub End Module
Passing arg ByExpr (delayed lazy eval) and ByHandle
ID: 14
using uCalcSoftware;
var uc = new uCalc();
static void MySum(uCalc.Callback cb) {
var Total = 0.0;
var Expr = cb.ArgExpr(1);
var Start = cb.Arg(2);
var Finish = cb.Arg(3);
var Variable = cb.ArgItem(4);
for (double x = Start; x <= Finish; x++) {
Variable.Value(x);
Total += Expr.Evaluate();
}
cb.Return(Total);
}
uc.DefineVariable("x");
uc.DefineFunction("Sum(ByExpr Expr, Start, Finish, ByHandle Var)", MySum);
Console.WriteLine(uc.Eval("Sum(x ^ 2, 1, 10, x)"));
385 using uCalcSoftware; var uc = new uCalc(); static void MySum(uCalc.Callback cb) { var Total = 0.0; var Expr = cb.ArgExpr(1); var Start = cb.Arg(2); var Finish = cb.Arg(3); var Variable = cb.ArgItem(4); for (double x = Start; x <= Finish; x++) { Variable.Value(x); Total += Expr.Evaluate(); } cb.Return(Total); } uc.DefineVariable("x"); uc.DefineFunction("Sum(ByExpr Expr, Start, Finish, ByHandle Var)", MySum); Console.WriteLine(uc.Eval("Sum(x ^ 2, 1, 10, x)"));
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call MySum(uCalcBase::Callback cb) {
auto Total = 0.0;
auto Expr = cb.ArgExpr(1);
auto Start = cb.Arg(2);
auto Finish = cb.Arg(3);
auto Variable = cb.ArgItem(4);
for (double x = Start; x <= Finish; x++) {
Variable.Value(x);
Total += Expr.Evaluate();
}
cb.Return(Total);
}
int main() {
uCalc uc;
uc.DefineVariable("x");
uc.DefineFunction("Sum(ByExpr Expr, Start, Finish, ByHandle Var)", MySum);
cout << uc.Eval("Sum(x ^ 2, 1, 10, x)") << endl;
}
385 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call MySum(uCalcBase::Callback cb) { auto Total = 0.0; auto Expr = cb.ArgExpr(1); auto Start = cb.Arg(2); auto Finish = cb.Arg(3); auto Variable = cb.ArgItem(4); for (double x = Start; x <= Finish; x++) { Variable.Value(x); Total += Expr.Evaluate(); } cb.Return(Total); } int main() { uCalc uc; uc.DefineVariable("x"); uc.DefineFunction("Sum(ByExpr Expr, Start, Finish, ByHandle Var)", MySum); cout << uc.Eval("Sum(x ^ 2, 1, 10, x)") << endl; }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub MySum(ByVal cb As uCalc.Callback)
Dim Total = 0.0
Dim Expr = cb.ArgExpr(1)
Dim Start = cb.Arg(2)
Dim Finish = cb.Arg(3)
Dim Variable = cb.ArgItem(4)
For x As Double = Start To Finish
Variable.Value(x)
Total += Expr.Evaluate()
Next
cb.Return(Total)
End Sub
Public Sub Main()
Dim uc As New uCalc()
uc.DefineVariable("x")
uc.DefineFunction("Sum(ByExpr Expr, Start, Finish, ByHandle Var)", AddressOf MySum)
Console.WriteLine(uc.Eval("Sum(x ^ 2, 1, 10, x)"))
End Sub
End Module
385 Imports System Imports uCalcSoftware Public Module Program Public Sub MySum(ByVal cb As uCalc.Callback) Dim Total = 0.0 Dim Expr = cb.ArgExpr(1) Dim Start = cb.Arg(2) Dim Finish = cb.Arg(3) Dim Variable = cb.ArgItem(4) For x As Double = Start To Finish Variable.Value(x) Total += Expr.Evaluate() Next cb.Return(Total) End Sub Public Sub Main() Dim uc As New uCalc() uc.DefineVariable("x") uc.DefineFunction("Sum(ByExpr Expr, Start, Finish, ByHandle Var)", AddressOf MySum) Console.WriteLine(uc.Eval("Sum(x ^ 2, 1, 10, x)")) End Sub End Module