NCalc Expression.Evaluate()提供错误的输出

时间:2015-06-22 07:38:58

标签: c# ncalc

我们有像

这样的代码
ncalcFormula = "[OD1000]=[OD1100]+[OD1200]+[OD1350]+[OD1450]"    
var expression = new Expression(ncalcFormula);  

foreach (FormulaParameter fp in parsedParameters)
{
    expression.Parameters[fp.QuestionKey] = fp.Value;
}    
object res = expression.Evaluate();

原始表达: - [OD1000] = [OD1100] + [OD1200] + [OD1350] + [OD1450]

评估后称为解析表达式: - {([OD1000])=(((([OD1100])+([OD1200])+([OD1350])+([OD1450])}

通过添加参数值进行测试,如下所示

1)9.33 = 2.25 + 3.25 + 1.5 + 2.33

2)15617031.48 = 15226149.36 + 166208.00 + 0.00 + 224674.12

评估后1)将返回true,2)将返回false,尽管两个表达式都是正确的。

请建议。

2 个答案:

答案 0 :(得分:0)

使用' equlas'用于比较浮点值的运算符是一个坏主意,因为计算结果必须适合浮点表示。为了正确执行比较,您需要指定容差,即结果可以与预期值偏离多少。我重写了你的公式,以增加一些“公差”。

        var ncalcFormula = "Abs([OD1000]-([OD1100]+[OD1200]+[OD1350]+[OD1450])) < 0.00001";    
        var expression = new Expression(ncalcFormula);  
        expression.Parameters["OD1000"] = 15617031.48;
        expression.Parameters["OD1100"] = 15226149.36;
        expression.Parameters["OD1200"] = 166208.00;
        expression.Parameters["OD1350"] =  0.00;
        expression.Parameters["OD1450"] = 224674.12;

答案 1 :(得分:0)

我从其他论坛得到了确切的答案: - 这是浮点数存储方式的限制。

当您使用float(System.Single)或double(System.Double)时,数字将使用二进制格式存储,该格式无法精确表示每个十进制值。您经常会发现,由于其最低有效数字的差异,看起来相同的数字不会被视为相等。这在MSDN上记录[^]。

如果您使用表达式#2并在常规C#代码中对其进行评估,您将看到它仍然返回false。如果您使用指定的R格式打印结果,您将看到原因:

Console.WriteLine(15617031.48 == 15226149.36 + 166208.00 + 0.00 + 224674.12); //假

Console.WriteLine(&#34; {0:R}&#34;,15617031.48); // 15617031.48

Console.WriteLine(&#34; {0:R}&#34;,15226149.36 + 166208.00 + 0.00 + 224674.12); // 15617031.479999999

如果您需要精确的十进制计算,则应该使用十进制类型[^]。