【问题标题】:What is the best way to execute math expression? [duplicate]执行数学表达式的最佳方法是什么? [复制]
【发布时间】:2010-11-12 09:04:46
【问题描述】:

可能的重复:
Is there a string math evaluator in .NET?
Best and shortest way to evaluate mathematical expressions

我有一个字符串变量

string exp = "12+34+4*56+(23*45+12)2/30"

最好的方法是什么?不使用第三方dll?

【问题讨论】:

  • “在做吗?”这是什么意思?
  • @Liviu M. - 我猜他想计算嵌入在字符串中的表达式的结果。
  • @Øyvind Bråthen,是的,你是对的
  • 一种方法是打开 Windows Calculator,然后复制其中的字符串(当然是通过编程方式)。但它不是很聪明。可能有一些用于 .NET Framework 的库可以从字符串中解析表达式。
  • 您正在寻找自己编写代码,或者只是想找到可以完成这项工作的东西?

标签: c#


【解决方案1】:

您需要一个数学表达式解析器。我认为最好的方法是不要重新发明轮子。现有的开源解决方案NCalc 是一个不错的选择。

【讨论】:

  • +1 表示简洁、正确、完整,包括示例。我真的想要一个开源解决方案。除非你想学习如何编写这样的东西。然后我会添加对 Niklaus Wirth 的“编译器构造”一书的参考。
【解决方案2】:

首先将其转换为表达式树。如果您使用内置的 Expression 类,您将免费获得一个编译方法,该方法为您提供编译的委托,因此评估速度非常快。如果您想针对不同的参数评估表达式,这很有用。

【讨论】:

    【解决方案3】:

    Knuth 的经典方法是首先将中缀表达式转换为后缀表达式,然后计算后缀表达式,请参阅link text。这两个步骤都使用堆栈来完成大部分处理,并且相当容易做到。

    【讨论】:

      【解决方案4】:

      使用 IronPython:

      ScriptEngine engine = PythonSingleton.Instance.ScriptEngine;
      ScriptSource source =
      engine.CreateScriptSourceFromString(code, SourceCodeKind.Expression);
      
      Object res = source.Execute();
      

      (复制自this article的代码)

      【讨论】:

        【解决方案5】:

        然后在字符串的开头和结尾添加[、] 作为运算符:

        读取数字将它们填充到堆栈中并读取运算符并执行相同操作,当您丰富其值小于或等于堆栈中前一个运算符的运算符时,弹出前一个运算符并作用于数字堆栈中的可用数字: *:3, /:3, ):4, +:1,-:1

        [12+34+4*56] ==>
        Round 1: Numbers Stack: 12, Operator stack:[
        Round 2: Numbers Stack: 12, Operator stack:[, +(1)
        Round 3: Numbers Stack:12,34, Operator stack: [,+(1)
        Round 4: Numbers Stack:12,34, Visited new operator with same or lower value (1) remove previous operator and pop 2 number from number stack and operate on them: So
        Round 4: Numbers Stack:46, Operator stack: [,+(1)
        Round 5: Numbers Stack:46,4 , Operator stack: [,+(1)
        Round 6: Numbers Stack:46,4 , Operator stack: [,+(1),*(2)
        Round 7: Numbers Stack:46,4,56, Operator stack: [,+(1),*(2)
        Round 7: Numbers Stack:46,4,56, Operator stack: [,+(1),*(2) now operator item `]` want to be add, and it's priority is lower than all operators so operators sould be remove from stack and by each operator one number going to be removed:
        Round 7: Numbers Stack:46,224 Operator stack: [,+(1),
        Round 8: Numbers Stack:270 Operator stack: [,
        Round 8: return 270, because ']' intered in  Operator stack
        

        【讨论】:

        • 这不是“重新发明轮子”吗?有几十个数值表达式评估器经过充分测试,得到很好的支持并且比这更强大。为生产代码再写一个有什么意义?
        • @nikie,恕我直言 OP 想不使用第三方来做,我写这个也是因为算法简单有趣。
        • 我同意这个算法很有趣,而且它是一个很好的编程练习。但它还没有准备好生产(恕我直言,这就是 OP 想要的)。例如,我看不到任何针对良好语法错误的规定(通常是编写解析器中最难的部分!)。
        • 顺便说一句,我很好奇:这个算法如何处理一元减号?例如4 * -5 和 -4 * +5 有效,但 4 * / 3 无效。
        • @nikie,它不能像你写的那样处理减号,但 OP 没有询问它,并且在他的示例中没有任何关于它的内容。
        【解决方案6】:

        这有点hack,但我在.net中使用了javascript的eval函数:

        var myEngine = Microsoft.JScript.Vsa.VsaEngine.CreateEngine();
        string result =  Microsoft.JScript.Eval.JScriptEvaluate(expression, myEngine).ToString();
        

        如果需要,您还可以将数学函数混合到表达式中

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-09-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多