NCalc指定类型

时间:2016-03-30 08:14:48

标签: c# ncalc

我们有一个使用Ncalc来计算字符串的通用计算例程。但是,当乘法中的值足够小以至于Ncalc将它们视为int时,我们遇到了一个问题,但结果对于int来说太大了。

示例:

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

这会导致负的int值。

有没有办法迫使Ncalc长时间使用计算?

我已尝试使用参数,但这有效,但这意味着要对我们的代码进行重大改写,如果可能,我希望避免使用。

由于

2 个答案:

答案 0 :(得分:2)

NCalc使用Int32作为整数数据类型,然后您不能强制将数字计算为Int64。但是,如果您不使用内置数学函数并依赖 plain 数学运算符,则可以将数字转换为long,它将调用正确的运算符。我们来看看:

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]);
    }
};

请注意,您无法直接将Int32盒装Int64参数投放到Convert.ToInt64(),然后您必须使用(long)(int)args.EvaluateParameters()[0]或双重投射:var result = expr.Evaluate(); Console.WriteLine("Result is: {0} (type {1})", result, result.GetType()); 。现在你可以检查结果是否正确:

long

执行了正确的类型转换,然后您无需两个值投射到decimal

请注意,您也可以直接使用浮点数(NCalc中的var expr = new NCalc.Expression("1740263.0 * 1234.0"); )并且您不会遇到这样的问题:

spring-boot

答案 1 :(得分:0)

您可以使用正则表达式从字符串中提取所有数字,将其替换为参数,然后将参数设置为转换后的数字。在这个例子中,我将int数字替换成十进制数。

string myCalculationString = "1000000 * 10000000";
striny myPattern = @"-?\d+(,\d+)*(\.\d+(e\d+)?)?";

MatchCollection matches =
Regex.Matches(convertedCalculation, myPattern );

int matchCount = 0;
convertedCalculation = Regex.Replace(convertedCalculation,
myPattern , m => "[p" + matchCount++ + "]");

for (int i = 0; i < matches.Count; i++)
    {
       Match match = matches[i];
       decimal number = Convert.ToDecimal(match.Value);
       expression.Parameters.Add($"p{i}", number);
    }

 decimal result = (decimal)expression.Evaluate();

注意我没有很好地测试正则表达式,但它似乎适用于正/负数并允许可选的小数点。如果任何数字或结果超出了小数

的界限,这也会引发错误