-1

方法?しかし、文字列を一度だけ解析し、このようなインターフェースを持つパーサーが必要です

Func<double,double> MathEvaluator(string input)

またはこのように

LambdaExpression MathEvaluator(string input)

それは存在しますか?

4

3 に答える 3

2

RickOliver、およびMaxの回答によって提供された結果を引用して、このスレッドを参照したいと思います。

どちらが要件に最も適しているかを熟考する必要があります。たとえば、Math Parser .NET は^べき乗をサポートしていますが、他のパーサーはサポートしていません。

于 2013-02-28T19:44:04.790 に答える
1

だから私はライブラリを作りました、もしあなたが望むなら、あなたはそれを使うことができます、それで十分だと思います。a^b のような構造を Math.Pow(a,b) などに置き換える正規表現がいくつかあります。より良いかもしれませんが、私にとっては大変な作業ですが、取り組んでいます。

using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.CSharp;

namespace MathEvalNS
{
public class MathEvaluator
{
    private readonly Delegate parsedFunction;
    private readonly string normalized;
    public double Invoke(double x)
    {
        if (parsedFunction == null)
            throw new NullReferenceException("No function to invoke");
        return (double)parsedFunction.DynamicInvoke(x);
    }
    private const string Begin =
        @"using System;
namespace MyNamespace
{
    public static class LambdaCreator 
    {
        public static Func<double,double> Create()
        {
            return (x)=>";
        private const string End = @";
        }
    }
}";

    public MathEvaluator(string input)
    {
        normalized = Normalize(input);
        var provider = new CSharpCodeProvider();
        var parameters = new CompilerParameters { GenerateInMemory = true };
        parameters.ReferencedAssemblies.Add("System.dll");
        CompilerResults results = provider.CompileAssemblyFromSource(parameters, Begin + normalized + End);
        try
        {
            var cls = results.CompiledAssembly.GetType("MyNamespace.LambdaCreator");
            var method = cls.GetMethod("Create", BindingFlags.Static | BindingFlags.Public);
            parsedFunction = (method.Invoke(null, null) as Delegate);
        }
        catch (FileNotFoundException)
        {
            throw new ArgumentException();
        }
    }

    private string Normalize(string input)
    {
        return input.ReplaceMath().ReplacePow().ReplaceMultipling().ReplaceToDoubles();
    }
}

public static class StringHelper
{
    public static string ReplaceMultipling(this string input)
    {
        return Regex.Replace(input, @"(\d+)(x)", @"$1*$2");
    }

    public static string ReplacePow(this string input)
    {
        var result = input.ReplacePow(@"(\d*x)\^(\d+\.?\d*)");
        return result.ReplacePow(@"\(([^\^]+)\)\^(\d+\.?\d*)");
    }

    private static string ReplacePow(this string input, string toReplace)
    {
        return Regex.Replace(input, toReplace, "Math.Pow($1,$2)");
    }

    public static string ReplaceToDoubles(this string input)
    {
        return Regex.Replace(input, @"(\d+)(?:[^\.]\d+)", "$1.0");
    }

    public static string ReplaceMath(this string input)
    {
        return
            input.ReplaceMath("sin", @"Math.Sin")
                 .ReplaceMath("cos", @"Math.Cos")
                 .ReplaceMath("ctg", @"1.0/Math.Tan")
                 .ReplaceMath("tg", @"Math.Tan");
    }

    private static string ReplaceMath(this string input, string name, string dotNetName)
    {
        return Regex.Replace(input, name, dotNetName, RegexOptions.IgnoreCase);
    }
}
}
于 2013-03-01T05:52:44.470 に答える
0

私は MathParser を持っています: http://github.com/MathewSachin/MathParser

私はあなたが望むことが次のようにできることを期待しています:

Fuc<double, double> Parse(string Expression)
{
    MathParser P = new MathParser();
    Variable V = new Variable("x", 0); // The Variable you use with default value
    P.Variables.Add(V);

    P.Parse(Expression);

    return (Input) =>
        {
            V.Value = Input;
            return P.Evaluate();
        }
}

私が恐れているのはガベージコレクションだけです。

于 2015-10-16T08:48:00.550 に答える