Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NCalc specify type

Tags:

c#

ncalc

We have a generic calculation routine using Ncalc to evaluate a string. However we are running across a problem when the values in a multiplication are small enough that Ncalc sees them as int however the result is too big for an int.

Example:

        var expr = new NCalc.Expression("1740263 * 1234");
        object result = expr.Evaluate();
        Console.WriteLine(result.ToString());
        Console.ReadKey();

This results in a negative int value.

Is there any way to force Ncalc to use long for the calculation?

I have tried using parameters and this works but it would mean a major rewrite of our code to implement and I would like to avoid it if possible.

Thanks

like image 288
user2380829 Avatar asked Mar 30 '16 08:03

user2380829


1 Answers

NCalc uses Int32 as integer data type then you can't force a number to be calculated as Int64. However if you don't use built-in math functions and you rely on plain mathematical operators you may convert a number to long and it will invoke correct operators. Let's see it:

var expr = new NCalc.Expression("CLng(1740263) * 1234");
expr.EvaluateFunction += delegate(string name, NCalc.FunctionArgs args)
{
    // Nostalgic CLng function...
    if (String.Equals(name, "CLng", StringComparison.CurrentCultureIgnoreCase))
    {
        args.HasResult = true;
        args.Result = Convert.ToInt64(args.EvaluateParameters()[0]);
    }
};

Please note that you can't directly cast boxed Int32 parameter to Int64 then you have to use Convert.ToInt64() or double cast: (long)(int)args.EvaluateParameters()[0]. Now you can check result is correct:

var result = expr.Evaluate();
Console.WriteLine("Result is: {0} (type {1})",
    result, result.GetType());

Proper type conversion is performed then you don't need to cast both values to long.

Note that you may also directly use floating point numbers (decimal in NCalc) and you won't have such problems:

var expr = new NCalc.Expression("1740263.0 * 1234.0");
like image 112
Adriano Repetti Avatar answered Nov 12 '22 21:11

Adriano Repetti