Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# NET中是否有字符串数学计算器?_C#_.net - Fatal编程技术网

C# NET中是否有字符串数学计算器?

C# NET中是否有字符串数学计算器?,c#,.net,C#,.net,如果我有一个包含有效数学表达式的字符串,例如: String s = "1 + 2 * 7"; 在.NET中是否有一个内置的库/函数可以为我解析和计算该表达式并返回结果?在本例中,15.对于在Silverlight上使用C#开发的任何人,我刚刚发现了一个非常巧妙的技巧,它允许通过调用Javascript引擎来计算表达式: double result = (double) HtmlPage.Window.Eval("15 + 35"); 您可以添加对Microsoft脚本控制库(COM)的引用

如果我有一个包含有效数学表达式的字符串,例如:

String s = "1 + 2 * 7";

在.NET中是否有一个内置的库/函数可以为我解析和计算该表达式并返回结果?在本例中,15.

对于在Silverlight上使用C#开发的任何人,我刚刚发现了一个非常巧妙的技巧,它允许通过调用Javascript引擎来计算表达式:

double result = (double) HtmlPage.Window.Eval("15 + 35");

您可以添加对Microsoft脚本控制库(COM)的引用,并使用类似的代码计算表达式。(也适用于JScript。)

编辑-C#版本


编辑-脚本控件是COM对象。在项目的“添加引用”对话框中,选择“COM”选项卡并向下滚动到“Microsoft脚本控制1.0”并选择“确定”。

实际上有一种内置的名称空间-您可以使用XPath名称空间! 尽管需要重新格式化字符串以使用XPath表示法进行确认。我使用了这样的方法来处理简单表达式:

    public static double Evaluate(string expression)
    {
        var xsltExpression = 
            string.Format("number({0})", 
                new Regex(@"([\+\-\*])").Replace(expression, " ${1} ")
                                        .Replace("/", " div ")
                                        .Replace("%", " mod "));

        return (double)new XPathDocument
            (new StringReader("<r/>"))
                .CreateNavigator()
                .Evaluate(xsltExpression);
    }
+ (addition)
- (subtraction)
* (multiplication)
/ (division)
% (modulus)
公共静态双重求值(字符串表达式)
{
变量xsltExpression=
格式(“数字({0})”,
新的正则表达式(@“([\+\-\*])”)。替换(表达式“${1}”)
.替换(“/”,“div”)
.替换(“%”,“mod”);
返回(双重)新XPathDocument
(新StringReader(“”)
.CreateNavigator()
.评估(xsltExpression);
}
你看到了吗

它是可扩展的、快速的(例如有自己的缓存),使您能够通过处理EvaluateFunction/EvaluateParameter事件在运行时提供自定义函数和变量。它可以解析的示例表达式:

Expression e = new Expression("Round(Pow(Pi, 2) + Pow([Pi2], 2) + X, 2)"); 

  e.Parameters["Pi2"] = new Expression("Pi * Pi"); 
  e.Parameters["X"] = 10; 

  e.EvaluateParameter += delegate(string name, ParameterArgs args) 
    { 
      if (name == "Pi") 
      args.Result = 3.14; 
    }; 

  Debug.Assert(117.07 == e.Evaluate()); 

它还以本机方式处理unicode和许多数据类型。如果你想更改语法,它附带一个鹿角锉。还有一个fork支持MEF加载新函数

如果您需要非常简单的东西,可以使用
数据表

Dim dt作为新数据表
添加(“A”,GetType(整数))
添加(“B”,GetType(整数))
添加(“C”,GetType(整数))
Add(新对象(){12,13,DBNull.Value})
Dim boolResult作为布尔值=dt。选择(“A>B-2”)。长度>0
Add(“result”,GetType(Integer),“A+B*2+ISNULL(C,0)”)
Dim valResult作为对象=dt.行(0)(“结果”)
名称空间CalcExp
{
内部课程计划
{
私有静态void Main(字符串[]args)
{
双精度=评估(“4+5/2-1”);
控制台写入线(res);
}
公共静态双重求值(字符串表达式)
{
var-xsltExpression=
格式(“数字({0})”,
新的正则表达式(@“([\+\-\*])”)。替换(表达式“${1}”)
.替换(“/”,“div”)
.替换(“%”,“mod”);
//ReSharper禁用PossibleNullReferenceException
返回(双重)新XPathDocument
(新StringReader(“”)
.CreateNavigator()
.评估(xsltExpression);
//ReSharper还原可能的NullReferenceException
}
}
}

奇怪的是,这个著名而古老的问题没有一个答案暗示着内置的“把戏”。给你

double result = Convert.ToDouble(new DataTable().Compute("1 + 2 * 7", null));
表达式中支持以下算术运算符:

    public static double Evaluate(string expression)
    {
        var xsltExpression = 
            string.Format("number({0})", 
                new Regex(@"([\+\-\*])").Replace(expression, " ${1} ")
                                        .Replace("/", " div ")
                                        .Replace("%", " mod "));

        return (double)new XPathDocument
            (new StringReader("<r/>"))
                .CreateNavigator()
                .Evaluate(xsltExpression);
    }
+ (addition)
- (subtraction)
* (multiplication)
/ (division)
% (modulus)

更多信息:关于表达式语法。

我还想看看Jace()。Jace是一个高性能数学解析器和计算引擎,支持所有.NET版本(.NET 4.x、Windows Phone、Windows Store等)。Jace也可以通过NuGet获得:

几年前我实现了一个表达式解析器,并在年和最近发布了一个版本。它包含一个ExecutionContext类,可以计算一组表达式,例如:

  • MV=价格*数量
  • 价格=(买入+卖出)/2
  • 出价=.6
  • Ask=.8
它还内置了循环引用检查,这有助于避免堆栈溢出。

快速轻量级表达式计算器

语言参考

  • 算术运算符示例:a*2+b^2-100%5
  • 比较运算符示例:a 100
  • AndOrXorNotOperators示例(逻辑):a>100而非b=100
  • 换档操纵器示例:100>>2
  • 连接示例:“abc”+“def”
  • 索引示例:arr[i+1]+100
  • 文字
  • 铸造示例:100+铸造(obj,int)
  • 条件运算符示例:如果(a>100和b>10,“两者都较大”、“较小”)
  • 操作器示例(列表):如果(100英寸(100,200,300,-1),“英寸”,“不英寸”)
  • 类型上的重载运算符
例如:

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

输出:50

最初我使用c#包装器。这很快。我所知道的唯一更快的解决方案是。如果您正在寻找其他解决方案,您可以签出

但是对于.Net,您可以使用内置支持在运行时编译代码。其想法是将“模板”源文件作为嵌入式资源,您可以在其中替换评估公式。然后将这个准备好的类源代码传递给编译器

基本模板可以如下所示:

public class CSCodeEvaler
{
    public double EvalCode()
    {
        return last = Convert.ToDouble(%formula%);
    }

    public double last = 0;
    public const double pi = Math.PI;
    public const double e = Math.E;
    public double sin(double value) { return Math.Sin(value); }
    public double cos(double value) { return Math.Cos(value); }
    public double tan(double value) { return Math.Tan(value); }
    ...
请注意将在其中放入表达式的%formula%

要编译,请使用类CSharpCodeProvider。我不想在这里输入完整的源代码。但可能会有帮助:


加载内存中的程序集后,可以创建类的实例并调用EvalCode。

最近我使用了mXparser,这是一个用于.NET和JAVA的数学解析器库。mXparser支持基本公式以及非常奇特/复杂的公式(包括变量、函数、运算符、迭代和递归)

一些用法示例:

例1:

Expression e = new Expression("1+2*7 + (sin(10) - 2)/3");
double v = e.calculate();
例2:

Argument x = new Argument("x = 5");
Expression e = new Expression("2*x+3", x);
double v = e.calculate();
例3:

Function f = new Function("f(x,y) = sin(x) / cos(y)");
Expression e = new Expression("f(pi, 2*pi) - 2", f);
double v = e.calculate();
福恩
Argument x = new Argument("x = 5");
Expression e = new Expression("2*x+3", x);
double v = e.calculate();
Function f = new Function("f(x,y) = sin(x) / cos(y)");
Expression e = new Expression("f(pi, 2*pi) - 2", f);
double v = e.calculate();
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();
        }
    }
}
<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" />
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);
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));
        }
    }
}
<PackageReference Include="MathNet.Symbolics" Version="0.20.0" />
var a = 6;
var b = 4.32m;
var c = 24.15m;
var engine = new ExpressionEvaluator();
engine.Evaluate("(((9-a/2)*2-b)/2-a-1)/(2+c/(2+4))", new { a, b, c});
dynamic dynamicEngine = new ExpressionEvaluator();

var a = 6;
var b = 4.5m;
var c = 2.6m;

dynamicEngine.Evaluate("(c+b)*a", a: 6, b: 4.5, c: 2.6);