NCalc: a good helper for mathematical operations


widgets Article
NCalc: a good helper for mathematical operations
Codeplex Software Package (Package) Information
Package name NCalc: Mathematical Expressions Evaluator for .NET
Author R & D Department of Evaluant Corporation
Current version 1.3.1 Stable
URL http://ncalc.codeplex.com/
Ease of use easy
Accessibility tools available when using this kit no
Basic knowledge Basic category use.
Use of .NET Math category.
The use of delegation (Delegate).

Mathematical expressions of love and hatred

When writing applications such as engineering calculations or business statistics, sometimes it is necessary to write some programs that deal with expressions to handle custom operations or evaluate execution results, such as sales statistics, Customer benefit evaluation, trigonometric function calculation, and other mathematical calculations, etc., these expressions are usually presented in this way:

 

If you want to do an expression entered by the user yourself, the program to be written will be much more complicated. Generally, it will be implemented using a stack or a binary expression tree as the basis, and it must be executed in conjunction with the execution. Change the order to arrange the priority order of the operators (for example, multiplication and division are higher than addition and subtraction, and the operations in parentheses are higher than the general operation priority order). If you want to add judgment logic, you need to consider more. If you have taken a course on data structure at a university, you should be familiar with expressions. Preorder, Inorder, and Postorder operations are basic knowledge of expressions. In addition to general mathematical expressions, the knowledge of expressions can also be widely used in many places, such as XPath in XML, or a large number of regular expressions used in string parsing (Regular Expression) are special types of expressions. The rules are customized by the developer. However, the average developer is less likely to write such high-level analytic expressions, as long as he knows how to write general mathematical expressions.

However, even if writing general mathematical expressions, the difficulty will not be lower than that of writing general programs. At this time, many people will think of the lovely JavaScript eval () method, which is a small function that can automatically evaluate expressions. Simple addition, subtraction, multiplication and division expressions can be calculated, but there is no such function in the .NET Framework. Although there are some methods to implement functions similar to the eval () method, most developers Don't know how to do it. Therefore, some developers on the Internet share their own processing methods for processing expressions. Among them, NCalc is a tool category for processing mathematical expressions on Codeplex.

Introduction to NCalc

NCalc, developed by the research and development team of Evaluant, is a tool category library that processes expression strings in the .NET Framework and returns the results. It supports several mathematical operations, logical operations, and custom function operations. , Such as this code:

[C #]

 

NCalc can directly analyze expression strings and find the results, which can effectively reduce the burden for developers who often write custom expressions (especially can save the workload of writing evaluation functions), Programs that want to use the company's own salary calculation method or bonus calculation method can use NCalc to assist development. For example, suppose the company has such a rule:

"Business people can get 0.5% of the company's total sales and multiply the bonus by the proportion of the individual level"

If a developer with Database development capabilities can easily develop it in SQL, but if it is not possible to touch the database, then the formula for calculating the bonus listed above is:

y = (000.5 * t) * c
  • y is the bonus amount.
  • t is the company's total sales.
  • c is the personal bonus ratio.

If the above formula uses general practice, it might be written like this:

[C #]

 

If it is written in NCalc, it is:

[C #]

 

It may be that readers do not feel the advantages of NCalc, but if the company announced today that the formula for calculating bonuses would be changed to this:

y = (000.5 * (t * c) +10000)
  • y is the bonus amount.
  • t is the company's total sales.
  • c is the personal bonus ratio.

Then the program that uses hard code (written in the code) should return to the original code and change its calculation method to recompile and deploy, but the program that uses NCalc only needs to change the string, other programs are not Need to move, the developer can move the string to the configuration file, so that as long as the formula changes, as long as the configuration file can be modified, the code can be completely moved.

Use NCalc

To use NCalc in a project, simply add a reference to the NCalc.dll file (downloaded from the Codeplex website) to the project, and use the NCalc namespace (using NCalc;) in the code. The expressions of NCalc are mainly in the Expression category, which can accept incoming Logic Expression objects and strings, and can set NCalc expression evaluation options. The options determine the processing behavior of NCalc, such as None, IgnoreCases, NoCache, and IterateParameters, etc.

NCalc supports the following operators:

Types of Operator Explanation
Logical

or, ||

and, &&

Logical operator.
Relational

=, ==, !=, <>

<, <=, >, >=

Conditional comparison operator.
Additive +,- Addition operator.
Multiplicative *, /,% Multiplication operator.
Bitwise &, |, ^, >>, << Bitwise operations and shift operators.
Unary !, not, ~,- Negative operator.
Primary (,), values Brackets and general numerical operators.

 

And the following numeric types:

Types of  Explanation
integer Integer type.
floating point number Floating point type.
scientific notation Scientific notation type (eg 1e + 100).
Dates and Times Date and time type, if you want to use this type, you need to use "#" mark, for example # 2009/12/4 #
Booleans Bollinger value, true / false
Strings String value.
Functions Functions, built-in 20 kinds of mathematical functions (all functions provided in the Math category, but some Math categories support, NCalc does not support), and two special functions (in and if), can refer to http://ncalc.codeplex.com/wikipage?title=functions a list of supported functions.
Parameters The parameter should be wrapped with "[" "]" in the expression string, and then set its value by Expression.Parameters, for example 2 + 5 + [pi], [pi] is the parameter.

 

For example, if a deposit of 250,000 yuan is deposited in a bank, and the bank deposit interest rate is 1.05%, then the question of how much this money will be in 20 years, we all know that the bank's deposit uses the compound interest formula, namely:

FV = PV (1 + p)
n
  • FV (Future Value) is the future value of the wealth.
  • PV (Present Value) is the current value of the wealth.
  • p is the annual interest rate (or annual rate of return).
  • n is the number of years.

To use NCalc to reproduce this formula, you can write the following code:

[C #]

 

Among them, because PV, p, and n are parameters, you need to use [PV], [p], and [n] to set, then use Expression.Parameters to give the parameters, and finally call Expression.Evaluate () to get the calculation result.

Another example is the usual shopping in shopping malls or shopping malls, the clerk will always say the zero-interest rate for the sixth-swipe credit card, or the low-interest-rate promotional method for the 12-segment credit card. % -6%), the formula for calculating the installment fee by using the credit card installment is:

V =
PV(1+p)
n
  • V is the amount to be paid in each period.
  • PV is the selling price of the product.
  • p is the bank's card processing fee rate.
  • n is the number of months (months).

To use NCalc to reproduce this formula, you can write the following code:

[C #]

 

If the parameter value of the formula comes from a different formula, it can also be handled in NCalc, or if the formula contains a custom function, NCalc will use delegation to let the developer set its content. For example, when a bank calculates annual interest, as long as it is a two-month period, 0.01% interest is added, then the previous formula of principal and interest and calculation can be rewritten as:

[C #]

 

It can be found in the above program that an Expression.EvaluateParameter delegation is used. This delegation will be called when evaluating the expression. This delegation can be used to specify the content of specific parameters. Each parameter will be set to name for the parameter name. The person only needs to compare the name and then give the value according to the name.

The above program can also be written in another way, that is, adding a function name of its own to the expression, for example:

[C #]

 

So how does NCalc know the function implementation in the expression? At this time, you can use the Expression.EvaluateFunction delegation. This delegation is used in the same way as the Expression.EvaluateParameter delegation. It also passes in a name (string type) and args (FunctionArgs type) parameters. The developer only needs to compare its name. Come out, and then set its execution result to FunctionArgs.Result.

[C #]

 

Conclusion

NCalc is very suitable for developers to support when they need a tool to automatically evaluate expressions. It can directly isolate the expressions from the code, and can change the formula content of the expressions without changing the parameters, especially suitable for the formulas. In an environment where the input parameters are variable (such as discount calculation or bonus calculation).

static int GetSavingInterests(int PV, double Rate, int Month)
{
    Expression e = new Expression("([PV] * GetRate([i])) / 12");
    e.Parameters["PV"] = PV;
    e.Parameters["i"] = Month;

    e.EvaluateFunction += delegate(string name, FunctionArgs args)
    {
        if (name == "GetRate")
            args.Result = (Convert.ToInt32(args.Parameters[0].Evaluate()) % 2 == 0) ? Rate + 0.0001 : Rate;
    };

    return Convert.ToInt32(e.Evaluate());
}

Expression e = new Expression("([PV] * GetRate()) / 12");

static int GetSavingInterests(int PV, double Rate, int Month)
{
    Expression e = new Expression("([PV] * [p]) / 12");
    e.Parameters["PV"] = PV;

    e.EvaluateParameter += delegate(string name, ParameterArgs args)
    {
        if (name == "p")
            args.Result = (Month % 2 == 0) ? Rate + 0.0001 : Rate;
    };

    return Convert.ToInt32(e.Evaluate());
}

static int GetPerMonthlyPayment(int PV, double Rate, int Months)
{
    Expression e = new Expression("([PV] * (1 + [p])) / [n]");
    e.Parameters["PV"] = PV;
    e.Parameters["p"] = Rate;
    e.Parameters["n"] = Months;

    return Convert.ToInt32(e.Evaluate());
}

static int GetFV(int PV, double Rate, int Years)
{
    Expression e = new Expression("[PV] * ((1 + [p]) ^ [n])");
    e.Parameters["PV"] = PV;
    e.Parameters["p"] = Rate;
    e.Parameters["n"] = Years;

    return (int)e.Evaluate();
}

static void CalcSalaryWithNCalc (DataTable RawTable)
{
    int totalAmount = 500000000;
    // The formula is defined in the string.
    Expression e = new Expression ("(0.05 * [t]) * [c]");
    foreach (DataRow row in RawTable.Rows)
    {
        double levelFactor = 0.0;

        switch ((SalaryAwardLevel) row [1])
        {
            case SalaryAwardLevel.Normal:
                levelFactor = 0.01;
                break;
            case SalaryAwardLevel.Silver:
                levelFactor = 0.02;
                break;
            case SalaryAwardLevel.WhiteSilver:
                levelFactor = 0.03;
                break;
            case SalaryAwardLevel.Gold:
                levelFactor = 0.04;
                break;
            case SalaryAwardLevel.WhiteGold:
                levelFactor = 0.05;
                break;
        }

        e.Parameters ["t"] = totalAmount;
        e.Parameters ["c"] = levelFactor;

        Console.WriteLine ("{0} 's salary award: {1: $ ###, ###, ###, ## 0}", row [0], e.Evaluate ());
    }
}

static void CalcSalaryWithoutNCalc (DataTable RawTable)
{
    int totalAmount = 500000000;

    foreach (DataRow row in RawTable.Rows)
    {
        double levelFactor = 0.0;

        switch ((SalaryAwardLevel) row [1])
        {
            case SalaryAwardLevel.Normal:
                levelFactor = 0.01;
                break;
            case SalaryAwardLevel.Silver:
                levelFactor = 0.02;
                break;
            case SalaryAwardLevel.WhiteSilver:
                levelFactor = 0.03;
                break;
            case SalaryAwardLevel.Gold:
                levelFactor = 0.04;
                break;
            case SalaryAwardLevel.WhiteGold:
                levelFactor = 0.05;
                break;
        }

        // Write the formula in the program.
        Console.WriteLine ("{0} 's salary award: {1: $ ###, ###, ###, ## 0}", row [0], 
((double) totalAmount * 0.05) * levelFactor);
    }
}

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

z = sin(x) + sin(y)
amount = amount + (0.05 * amount) + bonus_value
add me as friend!

widgets Related Articles

widgets Contribution

This article is contributed by Anonymous and text available under CC-SA-4.0