Is there a string math evaluator in .NET?

前端 未结 16 1411
长情又很酷
长情又很酷 2020-11-22 01:01

If I have a string with a valid math expression such as:

String s = \"1 + 2 * 7\";

Is there a built in library/function in .NET that will p

相关标签:
16条回答
  • 2020-11-22 01:35

    Yet another option now that Roslyn is available:

    You can use CodeAnalysis.CSharp.Scripting library for this.

    using Microsoft.CodeAnalysis.CSharp.Scripting;
    using System;
    
    namespace ExpressionParser
    {
        class Program
        {
            static void Main(string[] args)
            {
                //Demonstrate evaluating C# code
                var result = CSharpScript.EvaluateAsync("System.DateTime.Now.AddDays(-1) > System.DateTime.Now").Result;
                Console.WriteLine(result.ToString());
    
                //Demonstrate evaluating simple expressions
                var result2 = CSharpScript.EvaluateAsync(" 5 * 7").Result;
                Console.WriteLine(result2);
                Console.ReadKey();
            }
        }
    }
    

    nuget packages:

    <package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net461" />
    <package id="Microsoft.CodeAnalysis.Common" version="1.1.1" targetFramework="net461" />
    <package id="Microsoft.CodeAnalysis.CSharp" version="1.1.1" targetFramework="net461" />
    <package id="Microsoft.CodeAnalysis.CSharp.Scripting" version="1.1.1" targetFramework="net461" />
    <package id="Microsoft.CodeAnalysis.Scripting" version="1.1.1" targetFramework="net461" />
    <package id="Microsoft.CodeAnalysis.Scripting.Common" version="1.1.1" targetFramework="net461" />
    
    0 讨论(0)
  • 2020-11-22 01:35

    MathNet.Symbolics

    using System;
    using static MathNet.Symbolics.SymbolicExpression;
    using static System.Console;
    using static System.Numerics.Complex;
    using Complex = System.Numerics.Complex;
    
    namespace MathEvaluator
    {
        class Program
        {
            static readonly Complex i = ImaginaryOne;
    
            static void Main(string[] args)
            {
                var z = Variable("z");
                Func<Complex, Complex> f = Parse("z * z").CompileComplex(nameof(z));
                Complex c = 1 / 2 - i / 3;
                WriteLine(f(c));
    
    
                var x = Variable("x");
                Func<double, double> g = Parse("x * x + 5 * x + 6").Compile(nameof(x));
                double a = 1 / 3.0;
                WriteLine(g(a));
            }
        }
    }
    

    Don't forget to load

    <PackageReference Include="MathNet.Symbolics" Version="0.20.0" />
    
    0 讨论(0)
  • 2020-11-22 01:36

    Flee Fast Lightweight Expression Evaluator

    https://flee.codeplex.com

    Language Reference

    • ArithmeticOperators Example: a*2 + b ^ 2 - 100 % 5
    • ComparisonOperators Example: a <> 100
    • AndOrXorNotOperators Example (logical): a > 100 And Not b = 100
    • ShiftOperators Example: 100 >> 2
    • Concatenation Example: "abc" + "def"
    • Indexing Example: arr[i + 1] + 100
    • Literals
    • Casting Example: 100 + cast(obj, int)
    • ConditionalOperator Example: If(a > 100 and b > 10, "both greater", "less")
    • InOperator Example (List): If(100 in (100, 200, 300, -1), "in", "not in")
    • Overloaded Operators On Types

    Example :

    Imports Ciloci.Flee
    Imports Ciloci.Flee.CalcEngine
    Imports System.Math
    

        Dim ec As New Ciloci.Flee.ExpressionContext
        Dim ex As IDynamicExpression
        ec.Imports.AddType(GetType(Math))
    
        ec.Variables("a") = 10            
        ec.Variables("b") = 40               
        ex = ec.CompileDynamic("a+b")
    
        Dim evalData    
        evalData = ex.Evaluate()
        Console.WriteLine(evalData)
    

    The output : 50

    0 讨论(0)
  • 2020-11-22 01:37

    I implemented an expression parser a few years ago and had published a version of it in GitHub and Nuget:Albatross.Expression recently. It contains a ExecutionContext class that can evaluate a set of expressions such as:

    • MV = Price * Qty;
    • Price = (Bid + Ask)/2;
    • Bid = .6;
    • Ask = .8;

    It also has built in circular reference check which is useful to avoid a stack overflow.

    0 讨论(0)
  • 2020-11-22 01:39

    I would also have a look at Jace (https://github.com/pieterderycke/Jace). Jace is a high performance math parser and calculation engine that supports all the .NET flavors (.NET 4.x, Windows Phone, Windows Store, ...). Jace is also available through NuGet: https://www.nuget.org/packages/Jace

    0 讨论(0)
  • 2020-11-22 01:40

    A simple math parser is quite easy to build, and requires only a few lines of code:

    Take this flexible example:

    class RPN
    {
        public static double Parse( Stack<string> strStk )
        {
            if (strStk == null || strStk.Count == 0 )
            {
                return 0;
            }
            Stack<double> numStk = new Stack<double>();
            double result = 0;
    
            Func<double, double> op = null;
            while (strStk.Count > 0)
            {
                var s = strStk.Pop();
                switch (s)
                {
                    case "+":
                        op = ( b ) => { return numStk.Pop() + b; };
                        break;
                    case "-":
                        op = ( b ) => { return numStk.Pop() - b; };
                        break;
                    case "*":
                        op = ( b ) => { return numStk.Pop() * b; };
                        break;
                    case "/":
                        op = ( b ) => { return numStk.Pop() / b; };
                        break;
    
                    default:
                        double.TryParse(s, NumberStyles.Any, out result);
                        if (numStk.Count > 0)
                        {
                            result = op(result);
                        }
                        numStk.Push(result);
                        break;
                }
            }
            return result;
        }
    }
    
    ....
    var str = " 100.5 + 300.5 - 100 * 10 / 100";    
    str = Regex.Replace(str, @"\s", "", RegexOptions.Multiline);
    Stack<string> strStk = new Stack<string>(
         Regex.Split(str, @"([()*+\/-])", RegexOptions.Multiline).Reverse()
    );
    RPN.Parse(strStk);
    

    To enable precedence by bracketing a stack of stacks will suffice, such as archived by recursion. Anything between brackets is put on a new stack. Finally you can support math operations in a clean readable fashion by lambdas.

    0 讨论(0)
提交回复
热议问题