Jika saya memiliki string dengan ekspresi matematika yang valid seperti:
String s = "1 + 2 * 7";
Apakah ada pustaka / fungsi bawaan di .NET yang akan mengurai dan mengevaluasi ekspresi itu untuk saya dan mengembalikan hasilnya? Dalam kasus ini 15.
Jawaban:
Anda dapat menambahkan referensi ke Microsoft Script Control Library (COM) dan menggunakan kode seperti ini untuk mengevaluasi ekspresi. (Juga berfungsi untuk JScript.)
Dim sc As New MSScriptControl.ScriptControl() sc.Language = "VBScript" Dim expression As String = "1 + 2 * 7" Dim result As Double = sc.Eval(expression)
Edit - versi C #.
MSScriptControl.ScriptControl sc = new MSScriptControl.ScriptControl(); sc.Language = "VBScript"; string expression = "1 + 2 * 7"; object result = sc.Eval(expression); MessageBox.Show(result.ToString());
Edit - ScriptControl adalah objek COM. Dalam dialog "Tambahkan referensi" dari proyek tersebut pilih tab "COM" dan gulir ke bawah ke "Microsoft Script Control 1.0" dan pilih ok.
sumber
Aneh bahwa pertanyaan terkenal dan lama ini tidak memiliki jawaban yang menyarankan
DataTable.Compute
"trik" bawaan. Ini dia.double result = Convert.ToDouble(new DataTable().Compute("1 + 2 * 7", null));
Operator aritmatika berikut ini didukung dalam ekspresi:
Informasi lebih lanjut:
DataColumn.Expression
di Expression Syntax .sumber
Untuk siapa pun yang mengembangkan C # di Silverlight, inilah trik yang cukup rapi yang baru saja saya temukan yang memungkinkan evaluasi ekspresi dengan memanggil mesin Javascript:
double result = (double) HtmlPage.Window.Eval("15 + 35");
sumber
Pernahkah Anda melihat http://ncalc.codeplex.com ?
Ini dapat diperluas, cepat (misalnya memiliki cache sendiri) memungkinkan Anda untuk menyediakan fungsi dan varaibles kustom pada waktu proses dengan menangani peristiwa EvaluateFunction / EvaluateParameter. Contoh ekspresi yang dapat diurai:
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());
Ini juga menangani unicode & banyak tipe data secara asli. Itu datang dengan file tanduk jika Anda ingin mengubah grammer. Ada juga garpu yang mendukung MEF untuk memuat fungsi baru.
sumber
Sebenarnya ada semacam built-in - Anda dapat menggunakan namespace XPath! Meskipun itu mengharuskan Anda memformat ulang string untuk mengonfirmasi dengan notasi XPath. Saya telah menggunakan metode seperti ini untuk menangani ekspresi sederhana:
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); }
sumber
Awalnya saya menggunakan c # wrapper untuk muparser . Ini sangat cepat. Satu-satunya solusi yang lebih cepat yang saya tahu adalah exprtk . Jika Anda mencari solusi lain, Anda dapat memeriksa benchmark .
Tetapi dalam kasus .Net Anda dapat menggunakan dukungan bawaan untuk mengkompilasi kode pada saat runtime. Idenya adalah untuk memiliki file sumber "template" seperti sumber daya yang disematkan di mana Anda dapat mengganti rumus untuk evaluasi. Kemudian Anda meneruskan kode sumber kelas yang telah disiapkan ini ke kompilator.
Template dasar bisa terlihat seperti ini:
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); } ...
Perhatikan% formula% dimana ekspresi akan dimasukkan.
Untuk mengkompilasi gunakan kelas CSharpCodeProvider. Saya tidak ingin memasukkan secara lengkap sumbernya di sini. Tetapi jawaban ini mungkin membantu:
Setelah Anda memiliki perakitan memori dimuat Anda dapat membuat contoh kelas Anda dan memanggil EvalCode.
sumber
Namun pilihan lain sekarang setelah Roslyn tersedia:
Anda dapat menggunakan pustaka CodeAnalysis.CSharp.Scripting untuk ini.
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(); } } }
paket nuget:
<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" />
sumber
Baru-baru ini saya menggunakan mXparser, yang merupakan pustaka parser matematika untuk .NET dan JAVA. mXparser mendukung formula dasar serta formula yang sangat mewah / rumit (termasuk variabel, fungsi, operator, iterasi dan rekursi).
https://mxparser.codeplex.com/
https://mathparser.org/
Beberapa contoh penggunaan:
Contoh 1:
Expression e = new Expression("1+2*7 + (sin(10) - 2)/3"); double v = e.calculate();
Contoh 2:
Argument x = new Argument("x = 5"); Expression e = new Expression("2*x+3", x); double v = e.calculate();
Contoh 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();
Ditemukan baru-baru - dalam kasus Anda ingin mencoba sintaks (dan melihat kasus penggunaan lanjutan) Anda dapat men-download Scalar Kalkulator aplikasi yang didukung oleh mXparser.
salam Hormat
sumber
Jika Anda membutuhkan hal yang sangat sederhana, Anda dapat menggunakan
DataTable
:-)Dim dt As New DataTable dt.Columns.Add("A", GetType(Integer)) dt.Columns.Add("B", GetType(Integer)) dt.Columns.Add("C", GetType(Integer)) dt.Rows.Add(New Object() {12, 13, DBNull.Value}) Dim boolResult As Boolean = dt.Select("A>B-2").Length > 0 dt.Columns.Add("result", GetType(Integer), "A+B*2+ISNULL(C,0)") Dim valResult As Object = dt.Rows(0)("result")
sumber
Saya juga akan melihat Jace ( https://github.com/pieterderycke/Jace ). Jace adalah mesin penghitung dan parser matematika berperforma tinggi yang mendukung semua jenis .NET (.NET 4.x, Windows Phone, Windows Store, ...). Jace juga tersedia melalui NuGet: https://www.nuget.org/packages/Jace
sumber
Pengurai matematika sederhana cukup mudah dibuat, dan hanya memerlukan beberapa baris kode:
Ambil contoh fleksibel ini:
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);
Untuk mengaktifkan presedensi dengan tanda kurung, tumpukan tumpukan sudah cukup, seperti diarsipkan dengan rekursi. Apa pun di antara tanda kurung diletakkan di tumpukan baru. Akhirnya Anda dapat mendukung operasi matematika dengan cara yang mudah dibaca oleh lambda.
sumber
100.5 + 300.5 - 100 * 10 / 100 = 30.1
vs391
namespace CalcExp { internal class Program { private static void Main(string[] args) { double res = Evaluate("4+5/2-1"); Console.WriteLine(res); } public static double Evaluate(string expression) { var xsltExpression = string.Format("number({0})", new Regex(@"([\+\-\*])").Replace(expression, " ${1} ") .Replace("/", " div ") .Replace("%", " mod ")); // ReSharper disable PossibleNullReferenceException return (double)new XPathDocument (new StringReader("<r/>")) .CreateNavigator() .Evaluate(xsltExpression); // ReSharper restore PossibleNullReferenceException } } }
sumber
Saya menerapkan pengurai ekspresi beberapa tahun yang lalu dan baru-baru ini menerbitkan versi di GitHub dan Nuget: Albatross.Expression . Ini berisi kelas ExecutionContext yang bisa mengevaluasi sekumpulan ekspresi seperti:
Ini juga memiliki pemeriksaan referensi melingkar yang berguna untuk menghindari tumpukan melimpah.
sumber
Anda dapat menggunakan library Math-Expression-Evaluator yang saya buat sendiri. Mendukung ekspresi sederhana seperti
2.5+5.9
,17.89-2.47+7.16
,5/2/2+1.5*3+4.58
, ekspresi dengan tanda kurung(((9-6/2)*2-4)/2-6-1)/(2+24/(2+4))
dan ekspresi dengan variabel: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});
Anda juga dapat mengirimkan parameter sebagai variabel bernama:
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);
Ini mendukung .Net Standard 2.0 sehingga dapat digunakan dari .Net Core serta proyek .Net Full Framework dan tidak memiliki dependensi eksternal.
sumber
Penilai Ekspresi Cepat Ringan
https://flee.codeplex.com
Referensi Bahasa
Contoh:
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)
Outputnya: 50
sumber
MathNet. Simbolis
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)); } } }
Jangan lupa memuat
<PackageReference Include="MathNet.Symbolics" Version="0.20.0" />
sumber