Skip to content

Allied-Bits-Ltd/ncalc

Repository files navigation

NCalc

NCalc

GitHub Actions Workflow Status

NuGet downloads

NCalc is a fast and lightweight expression evaluator library for .NET, designed for flexibility and high performance. It supports a wide range of mathematical and logical operations. NCalc can parse any expression and evaluate the result, including static or dynamic parameters and custom functions. NCalc targets .NET 10, .NET 9, .NET 8, .NET Standard 2.0, and NET Framework 4.6.2 and later.

Advanced features

This version of NCalc contains a number of advanced features compared to the original NCalc project, such as

  • Assignable parameters (variables) including shortcut operators (+=, etc.).
  • Statement sequences (useful together with parameter assignments) which, in expressions, may be grouped using curly brackets (like in C-like languages).
  • Support for indexed expressions (when an expression evaluates to a list a string, it is possible to access individual elements or a range of elements and assign new values to individual elements).
  • Support for loops using the 'while' loop statement (it follows the regular C-like style) with 'break' and 'continue' flow control keywords.
  • Support for the 'if' statement, which follows the regular C-like style.
  • Support for C-Style (line and block) and Python-style comments.
  • User-defined functions with named parameters (right in the expression, yes).
  • Percent calculations.
  • Factorials (both regular and any complex factorials on integers are supported).
  • Ternary logic support in logical operations.
  • Parsing of complex numbers and operations with them.
  • Parsing of vectors and operations with them.
  • The 'return' flow control keyword that lets one return a value without completely evaluating the expression (useful in complex expressions with multiple statements, conditions, or loops, as well as with user-defined functions).
  • Advanced date and time parsing, which takes into account culture settings (current or specific culture or custom separators) and supports times with or without seconds as well as 12-hour time and ISO 8601 dates and times.
  • Parsing of humane date expressions like "3 days ago" or "in 5 weeks" (identifiers are customizable and multiple identifiers are supported).
  • Parsing of humane period expressions like "3 weeks 2 days 5 hours" (period identifiers are customizable and multiple identifiers per period are supported).
  • Basic calculations with dates and time spans - one can add and subtract dates and times, multiply and divide time periods.
  • Currency support, which takes into account culture settings (current or specific culture or custom symbols) and produces decimal result from the currency value.
  • Optional use of BigInteger and BigDecimal types for basic math operations and most built-in funcitons.
  • Underscores in numbers and currency values. Modern programming languages support underscores for readability. Support is built-in with binary, octal, and hex numbers, while support in decimal numbers requires a custom branch of Parlot.
  • Custom decimal and group separators in numbers and currency.
  • An optional secondary decimal number separator (requires a custom branch of Parlot ).
  • Raw strings which are not parsed for escape sequences.
  • C-Style octal literals.
  • Result Reference character. A pseudo-function that would let a user application return some value, such as the result of a previous calculation. This is handy when an expression should include this result multiple times.
  • Logical XOR operations.
  • Certain Unicode characters can be used as operators.
  • The option to use Unicode characters in identifiers (useful for greek letter constants used in physics).
  • Case-insensitive lookup for parameter and function names.
  • Optional non-recursive evaluator for large and complex expressions.
  • The possibility to reuse a pre-created parser or parsers when parsing multiple expressions.
  • Flags in ExpressionOptions to skip date and GUID parsers in order to speed up parsing.
  • Minor improvements in the asynchronous code (CancellationToken and ConfigureAwait(false) are present in all calls).
  • The main projects have been combined into one project.
  • The AOT-compatible version of the library.

If you are interested in seeing those features in action, check our ABCalc product.

Docs

Need help or want to learn more? Check NCalc docs.

Help

Important

If you need help, please open an issue and include the expression to help us better understand the problem. Providing this information will aid in resolving the issue effectively.

Getting Started

dotnet add package AlliedBits.NCalc
...
using NCalc;

Functionalities

Simple Expressions

var expression = new Expression("2 + 3 * 5");
Debug.Assert(17 == expression.Evaluate());

Evaluates .NET data types

Debug.Assert(123456 == new Expression("123456").Evaluate()); // integers
Debug.Assert(new DateTime(2001, 01, 01) == new Expression("#01/01/2001#").Evaluate()); // date and times
Debug.Assert(123.456 == new Expression("123.456").Evaluate()); // floating point numbers
Debug.Assert(true == new Expression("true").Evaluate()); // booleans
Debug.Assert("azerty" == new Expression("'azerty'").Evaluate()); // strings

Handles mathematical functional from System.Math

Debug.Assert(0 == new Expression("Sin(0)").Evaluate());
Debug.Assert(2 == new Expression("Sqrt(4)").Evaluate());
Debug.Assert(0 == new Expression("Tan(0)").Evaluate());

Evaluates custom functions

var expression = new Expression("SecretOperation(3, 6)");
expression.Functions["SecretOperation"] = (args) => {
    return (int)args[0].Evaluate() + (int)args[1].Evaluate();
};

Debug.Assert(9 == expression.Evaluate());

Handles unicode characters

Debug.Assert("経済協力開発機構" == new Expression("'経済協力開発機構'").Evaluate());
Debug.Assert("Hello" == new Expression(@"'\u0048\u0065\u006C\u006C\u006F'").Evaluate());
Debug.Assert("だ" == new Expression(@"'\u3060'").Evaluate());
Debug.Assert("\u0100" == new Expression(@"'\u0100'").Evaluate());

Define parameters, even dynamic or expressions

var expression = new Expression("Round(Pow([Pi], 2) + Pow([Pi2], 2) + [X], 2)");

expression.Parameters["Pi2"] = new Expression("Pi * [Pi]");
expression.Parameters["X"] = 10;

expression.DynamicParameters["Pi"] = _ => {
    Console.WriteLine("I'm evaluating π!");
    return 3.14;
};

Debug.Assert(117.07 == expression.Evaluate());

JSON Serialization

NCalc for .NET 8 and later has built-in support for polymorphic JSON serialization using System.Text.Json.

const string expressionString = "{waterLevel} > 4.0";

var logicalExpression = LogicalExpressionFactory.Create(expressionString, ExpressionOptions.NoCache); //Created a BinaryExpression object.

var jsonExpression = JsonSerializer.Serialize(logicalExpression);

var deserializedLogicalExpression = JsonSerializer.Deserialize<LogicalExpression>(jsonExpression); //The object is still a BinaryExpression.

var expression = new Expression(deserializedLogicalExpression);

expression.Parameters = new Dictionary<string, object> {
    {"waterLevel", 4.0}
};

var result = expression.Evaluate();

Lambda Expressions

var expression = new Expression("1 + 2");
Func<int> function = expression.ToLambda<int>();
Debug.Assert(function()); //3

Related projects

Parlot (Main project)

AlliedBits.Parlot (the fork with improvements required for Allied Bits enhancements of NCalc)

Fast and lightweight parser creation tools by Sébastien Ros that NCalc uses for its parser.

An arbitrary-precision decimal (base 10) floating-point number class by Adam White.

A powerful yet user-friendly calculator for complex expressions, offering multi-format results, persistent history, unlimited memory, and much more.

Fast Compiler for C# Expression Trees. Developed by Maksim Volkov

About

NCalc is a fast and lightweight expression evaluator library for .NET, designed for flexibility and high performance. It supports a wide range of mathematical and logical operations. This version of NCalc has tons of features not present in the original library.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors