Değerlendirme, "3 * (4 + 2)" verim int 18

oy
82

Bir işlev bir dize içinde bulunan bir sayısal ifadeyi değerlendirmek ve sonucu dönebilirsiniz .NET framework var mı? Fe:

string mystring = 3*(2+4);
int result = EvaluateExpression(mystring);
Console.Writeln(result); // Outputs 18

Benim yerini alabilecek standart bir çerçeve işlevi var mıdır EvaluateExpressionyöntemi ile?

Oluştur 02/12/2008 saat 10:57
kaynak kullanıcı
Diğer dillerde...                            


14 cevaplar

oy
3

Sen oldukça kolay (temelde, bir tür ve bir yönteme) uygun tüy sarma onunla CSharpCodeProvider aracılığıyla bu çalıştırabilir. Başka bir cevap önerdiği üzere, veya JavaScript - Aynı şekilde VB vb geçmesi olabilir. Başka bu noktada çerçeveye yerleşik bir şey bilmiyorum.

Ben de bu cephede daha iyi yeteneklerine sahip olabilir dinamik diller için verdiği destek ile bu NET 4,0 beklersiniz.

Cevap 02/12/2008 saat 11:00
kaynak kullanıcı

oy
36

Evet, C # derleyicisi zamanında değerlendirmek sağlayabilirsiniz.

Bkz: CSharpCorner

Cevap 02/12/2008 saat 11:01
kaynak kullanıcı

oy
-1

Kısa cevap: Ben öyle düşünmüyorum. C # .Net (baytkoduna) derlenir ve aynı bildiğim kadarıyla, zamanında dizeleri değerlendiremez. JScript Net Ancak olabilir; ama yine de bir ayrıştırıcı kod ve öneririm değerlendirmeyi kendiniz yığını tabanlı.

Cevap 02/12/2008 saat 11:02
kaynak kullanıcı

oy
1

Yok. Bazı harici kütüphanesini kullanmak veya kendi ayrıştırıcı yazmak gerekir. Bunu yapmak için zaman varsa, bunun oldukça ilginç bir proje olarak kendi ayrıştırıcı yazmak için öneriyoruz. Aksi takdirde böyle bir şey kullanmanız gerekecektir bcParser .

Cevap 02/12/2008 saat 11:03
kaynak kullanıcı

oy
3

Geçenlerde bir proje için bunu yapmak için gerekli ve ben kullanarak sona erdi IronPython bunu yapmak için. Sen motorun bir örneğini bildirmek ve sonra herhangi bir geçerli piton ifadesini geçmek ve sonucu alabilirsiniz. Sadece basit matematik ifadeleri yapıyoruz, o zaman yeterli olacaktır. Kodum benzer görünümlü sona erdi:

IronPython.Hosting.PythonEngine pythonEngine = new IronPython.Hosting.PythonEngine();
string expression = "3*(2+4)";
double result = pythonEngine.EvaluateAs<double>(expression);

Muhtemelen her ifadesi için motoru oluşturmak istemez olur. Ayrıca IronPython.dll bir başvuru ihtiyaç

Cevap 02/12/2008 saat 14:44
kaynak kullanıcı

oy
13

Sen "XpathNavigator.Evaluate" bakmak olabilir benim GridView matematiksel ifadeler işlemek için bu kullanmış ve bu benim için çalışıyor.

İşte benim program için kullanılan kod:

public static double Evaluate(string expression)
{
    return (double)new System.Xml.XPath.XPathDocument
    (new StringReader("<r/>")).CreateNavigator().Evaluate
    (string.Format("number({0})", new
    System.Text.RegularExpressions.Regex(@"([\+\-\*])")
    .Replace(expression, " ${1} ")
    .Replace("/", " div ")
    .Replace("%", " mod ")));
}
Cevap 13/09/2009 saat 09:47
kaynak kullanıcı

oy
46

Bunu dene:

static double Evaluate(string expression) {
  var loDataTable = new DataTable();
  var loDataColumn = new DataColumn("Eval", typeof (double), expression);
  loDataTable.Columns.Add(loDataColumn);
  loDataTable.Rows.Add(0);
  return (double) (loDataTable.Rows[0]["Eval"]);
}
Cevap 13/09/2009 saat 10:13
kaynak kullanıcı

oy
66

Oluşturulan meclisleri yüklenir ve hiçbir zaman yayımlanmaktadır olarak yapmak derleyici kullanma bellek sızıntıları ima eder. Aynı zamanda gerçek bir ifadesi tercüman kullanmaktan daha yeterli performansı var. Bu amaçla kullanabileceğiniz Ncalc bu sadece niyet ile açık kaynaklı bir çerçevedir. Zaten dahil olanlar yeterli değilse Ayrıca kendi değişkenleri ve özel işlevler tanımlayabilirsiniz.

Örnek:

Expression e = new Expression("2 + 3 * 5");
Debug.Assert(17 == e.Evaluate());
Cevap 14/10/2009 saat 06:47
kaynak kullanıcı

oy
8

Bu Yığınlar'ı kullanarak basit İfade Değerlendirici olduğunu

public class MathEvaluator
{
    public static void Run()
    {
        Eval("(1+2)");
        Eval("5*4/2");
        Eval("((3+5)-6)");
    }

    public static void Eval(string input)
    {
        var ans = Evaluate(input);
        Console.WriteLine(input + " = " + ans);
    }

    public static double Evaluate(String input)
    {
        String expr = "(" + input + ")";
        Stack<String> ops = new Stack<String>();
        Stack<Double> vals = new Stack<Double>();

        for (int i = 0; i < expr.Length; i++)
        {
            String s = expr.Substring(i, 1);
            if (s.Equals("(")){}
            else if (s.Equals("+")) ops.Push(s);
            else if (s.Equals("-")) ops.Push(s);
            else if (s.Equals("*")) ops.Push(s);
            else if (s.Equals("/")) ops.Push(s);
            else if (s.Equals("sqrt")) ops.Push(s);
            else if (s.Equals(")"))
            {
                int count = ops.Count;
                while (count > 0)
                {
                    String op = ops.Pop();
                    double v = vals.Pop();
                    if (op.Equals("+")) v = vals.Pop() + v;
                    else if (op.Equals("-")) v = vals.Pop() - v;
                    else if (op.Equals("*")) v = vals.Pop()*v;
                    else if (op.Equals("/")) v = vals.Pop()/v;
                    else if (op.Equals("sqrt")) v = Math.Sqrt(v);
                    vals.Push(v);

                    count--;
                }
            }
            else vals.Push(Double.Parse(s));
        }
        return vals.Pop();
    }
}
Cevap 16/11/2010 saat 13:54
kaynak kullanıcı

oy
4

Bu hak, sol yürütmeye, böylece ifadesini yürütmek için uygun normal parantez kullanmak gerekir edilir

    // 2+(100/5)+10 = 32
    //((2.5+10)/5)+2.5 = 5
    // (2.5+10)/5+2.5 = 1.6666
    public static double Evaluate(String expr)
    {

        Stack<String> stack = new Stack<String>();

        string value = "";
        for (int i = 0; i < expr.Length; i++)
        {
            String s = expr.Substring(i, 1);
            char chr = s.ToCharArray()[0];

            if (!char.IsDigit(chr) && chr != '.' && value != "")
            {
                stack.Push(value);
                value = "";
            }

            if (s.Equals("(")) {

                string innerExp = "";
                i++; //Fetch Next Character
                int bracketCount=0;
                for (; i < expr.Length; i++)
                {
                    s = expr.Substring(i, 1);

                    if (s.Equals("("))
                        bracketCount++;

                    if (s.Equals(")"))
                        if (bracketCount == 0)
                            break;
                        else
                            bracketCount--;


                    innerExp += s;
                }

                stack.Push(Evaluate(innerExp).ToString());

            }
            else if (s.Equals("+")) stack.Push(s);
            else if (s.Equals("-")) stack.Push(s);
            else if (s.Equals("*")) stack.Push(s);
            else if (s.Equals("/")) stack.Push(s);
            else if (s.Equals("sqrt")) stack.Push(s);
            else if (s.Equals(")"))
            {
            }
            else if (char.IsDigit(chr) || chr == '.')
            {
                value += s;

                if (value.Split('.').Length > 2)
                    throw new Exception("Invalid decimal.");

                if (i == (expr.Length - 1))
                    stack.Push(value);

            }
            else
                throw new Exception("Invalid character.");

        }


        double result = 0;
        while (stack.Count >= 3)
        {

            double right = Convert.ToDouble(stack.Pop());
            string op = stack.Pop();
            double left = Convert.ToDouble(stack.Pop());

            if (op == "+") result = left + right;
            else if (op == "+") result = left + right;
            else if (op == "-") result = left - right;
            else if (op == "*") result = left * right;
            else if (op == "/") result = left / right;

            stack.Push(result.ToString());
        }


        return Convert.ToDouble(stack.Pop());
    }
Cevap 14/03/2011 saat 11:18
kaynak kullanıcı

oy
3

DÜZENLEME: ben gerçekten bu biraz daha BODMAS uyumlu hale getirmek için ayrı ayrı lutfen toplama ve çıkarma çıkarmalıyız fark etti.

Onun Yığın tabanlı yaklaşım için Rajesh Jinaga Big teşekkürler. Benim ihtiyaçları için gerçekten yararlı buldum. Aşağıdaki kod ilk bölümleri işleme RAJESH yöntemi, hafif bir modifikasyonu olan, çarpma, daha sonra daha sonra ekleme ve çıkarma ile tamamlanır. Ayrıca ifadelerde boole mantığı kullanımına izin 1 ve yanlış 0'a olarak ele alınır gerçek ifadeler, içinde boole kullanılmasını sağlayacaktır.

public static double Evaluate(string expr)
    {
        expr = expr.ToLower();
        expr = expr.Replace(" ", "");
        expr = expr.Replace("true", "1");
        expr = expr.Replace("false", "0");

        Stack<String> stack = new Stack<String>();

        string value = "";
        for (int i = 0; i < expr.Length; i++)
        {
            String s = expr.Substring(i, 1);
            // pick up any doublelogical operators first.
            if (i < expr.Length - 1)
            {
                String op = expr.Substring(i, 2);
                if (op == "<=" || op == ">=" || op == "==")
                {
                    stack.Push(value);
                    value = "";
                    stack.Push(op);
                    i++;
                    continue;
                }
            }

            char chr = s.ToCharArray()[0];

            if (!char.IsDigit(chr) && chr != '.' && value != "")
            {
                stack.Push(value);
                value = "";
            }
            if (s.Equals("("))
            {
                string innerExp = "";
                i++; //Fetch Next Character
                int bracketCount = 0;
                for (; i < expr.Length; i++)
                {
                    s = expr.Substring(i, 1);

                    if (s.Equals("(")) bracketCount++;

                    if (s.Equals(")"))
                    {
                        if (bracketCount == 0) break;
                        bracketCount--;
                    }
                    innerExp += s;
                }
                stack.Push(Evaluate(innerExp).ToString());
            }
            else if (s.Equals("+") ||
                     s.Equals("-") ||
                     s.Equals("*") ||
                     s.Equals("/") ||
                     s.Equals("<") ||
                     s.Equals(">"))
            {
                stack.Push(s);
            }
            else if (char.IsDigit(chr) || chr == '.')
            {
                value += s;

                if (value.Split('.').Length > 2)
                    throw new Exception("Invalid decimal.");

                if (i == (expr.Length - 1))
                    stack.Push(value);

            }
            else
            {
                throw new Exception("Invalid character.");
            }

        }
        double result = 0;
        List<String> list = stack.ToList<String>();
        for (int i = list.Count - 2; i >= 0; i--)
        {
            if (list[i] == "/")
            {
                list[i] = (Convert.ToDouble(list[i - 1]) / Convert.ToDouble(list[i + 1])).ToString();
                list.RemoveAt(i + 1);
                list.RemoveAt(i - 1);
                i -= 2;
            }
        }

        for (int i = list.Count - 2; i >= 0; i--)
        {
            if (list[i] == "*")
            {
                list[i] = (Convert.ToDouble(list[i - 1]) * Convert.ToDouble(list[i + 1])).ToString();
                list.RemoveAt(i + 1);
                list.RemoveAt(i - 1);
                i -= 2;
            }
        }
        for (int i = list.Count - 2; i >= 0; i--)
        {
            if (list[i] == "+")
            {
                list[i] = (Convert.ToDouble(list[i - 1]) + Convert.ToDouble(list[i + 1])).ToString();
                list.RemoveAt(i + 1);
                list.RemoveAt(i - 1);
                i -= 2;
            }
        }
        for (int i = list.Count - 2; i >= 0; i--)
        {
            if (list[i] == "-")
            {
                list[i] = (Convert.ToDouble(list[i - 1]) - Convert.ToDouble(list[i + 1])).ToString();
                list.RemoveAt(i + 1);
                list.RemoveAt(i - 1);
                i -= 2;
            }
        }
        stack.Clear();
        for (int i = 0; i < list.Count; i++)
        {
            stack.Push(list[i]);
        }
        while (stack.Count >= 3)
        {
            double right = Convert.ToDouble(stack.Pop());
            string op = stack.Pop();
            double left = Convert.ToDouble(stack.Pop());

            if (op == "<") result = (left < right) ? 1 : 0;
            else if (op == ">") result = (left > right) ? 1 : 0;
            else if (op == "<=") result = (left <= right) ? 1 : 0;
            else if (op == ">=") result = (left >= right) ? 1 : 0;
            else if (op == "==") result = (left == right) ? 1 : 0;

            stack.Push(result.ToString());
        }
        return Convert.ToDouble(stack.Pop());
    }

Bunu yapmanın daha temiz bir yol olması muhtemeldir olduğunu biliyorum, vaka herkes yararlı bulduğu içinde kimliği sadece ona ilk göz paylaşmak istedik.

Cevap 11/06/2011 saat 10:34
kaynak kullanıcı

oy
10
static double Evaluate(string expression) { 
  var loDataTable = new DataTable(); 
  var loDataColumn = new DataColumn("Eval", typeof (double), expression); 
  loDataTable.Columns.Add(loDataColumn); 
  loDataTable.Rows.Add(0); 
  return (double) (loDataTable.Rows[0]["Eval"]); 
} 

nasıl çalıştığını açıklaması:

İlk olarak, kısmen bir tablo yapmak var loDataTable = new DataTable();sadece Veri Tabanı Engine (örneğin MS SQL) olduğu gibi.

Daha sonra, bazı özel parametrelerle bir sütun, ( var loDataColumn = new DataColumn("Eval", typeof (double), expression);).

"Eval"Parametre kolonu (SütunAdı niteliği) adıdır.

typeof (double)veri tipi koymak eşittir sütun, depolanacak olan System.Type.GetType("System.Double");yerine.

expressiondize Evaluateyöntem alır ve öznitelik depolanır Expressionsütunun. Bu nitelik sütun üzerinde soktu her satır "İfade" ile yerine getirmiş olacak ki (bariz) gerçekten belirli bir amaç için olduğunu ve bir SQL sorguda konabilir pratik wathever kabul eder. Bakın http://msdn.microsoft.com/en-us/library/system.data.datacolumn.expression(v=vs.100).aspx İfade özelliğinde konabilir bilmek ve nasıl değerlendirilir oluyor.

Sonra, loDataTable.Columns.Add(loDataColumn);sütun ekler loDataColumniçin loDataTablemasaya.

Sonra, bir satır yoluyla yapılan bir İfade özelliği olan kişiselleştirilmiş bir sütuna sahip tabloya eklenir loDataTable.Rows.Add(0);. Bu satırı, tablonun sütununda "Eval" nin hücre eklediğinizdeloDataTable , otomatik olarak "İfade" özniteliği ile fullfilled edilir ve bu operatörler varsa ve SQL Sorguları vb, bu değerlendirilen oluyor ve sonra hücreye saklanan, bu nedenle burada "sihirli" olur, operatörleri ile dize değerlendirilir ve bir hücreye saklanır ...

Son olarak, sadece arka arkaya 0 kolon "Eval" hücresine kayıtlı değer döndürür ve bir çift için bir dönüşüm yapmak (bir indeks, sıfırdan itibaren başlar s) return (double) (loDataTable.Rows[0]["Eval"]);.

Ve hepsi ... iş bitti!

Ve burada eaiser bir kod bir yöntem içinde değil ve çok anlatılmış ... Aynı işlevi gören anlamak için.

DataTable MyTable = new DataTable();
DataColumn MyColumn = new DataColumn();
MyColumn.ColumnName = "MyColumn";
MyColumn.Expression = "5+5/5"
MyColumn.DataType = typeof(double);
MyTable.Columns.Add(MyColumn);
DataRow MyRow = MyTable.NewRow();
MyTable.Rows.Add(MyRow);
return (double)(MyTable.Rows[0]["MyColumn"]);

İlk olarak, birlikte tablo oluşturmak DataTable MyTable = new DataTable();

Daha sonra, bir sütun ile DataColumn MyColumn = new DataColumn();

Sonra, sütuna bir isim koydu. Bu yüzden bu tabloya depolanan zaman bu içeriği içine arama yapabilirsiniz. aracılığıyla YapıldıMyColumn.ColumnName = "MyColumn";

Sonra İfade, işte 6'dır sonucu önceden tanımlanmış bir dize "5 + 5/5" seçeneği var bu durumda, dize türünde bir değişken koyabilirsiniz.

verilerin türü sütununa depolanacak MyColumn.DataType = typeof(double);

Tabloya Sütun ekle ... MyTable.Columns.Add(MyColumn);

Bir satır tabloya, kopyalar tablo yapısı için eklenecek olun DataRow MyRow = MyTable.NewRow();

tablosuyla satır ekle MyTable.Rows.Add(MyRow);

Ve kolonun üst üste 0 hücre değerini geri MyColumntablo MyTableilereturn (double)(MyTable.Rows[0]["MyColumn"]);

Ders bitmiş !!!

Cevap 16/03/2012 saat 00:56
kaynak kullanıcı

oy
110

Eğer değerlendirmek istiyorsanız bir dize ifadesi aşağıda kod parçacığını kullanın.

using System.Data;

DataTable dt = new DataTable();
var v = dt.Compute("3 * (2+4)","");
Cevap 14/06/2012 saat 08:03
kaynak kullanıcı

oy
2

Ramesh için çok teşekkürler. Ben bir veritabanı üzerinden bir dize çekin ve benim kodda boolean operasyonları yapmak için kullanabilirsiniz yaptığı basit bir kod versiyonunu kullandı.

x 1500 veya 2100 veya her hangi başka bir sayıdır.

işlev x> 1400 ve x <1600 gibi bir saklı değerlendirme olur

function = relation[0].Replace("and","&&").Replace("x",x);

DataTable f_dt = new DataTable();
var f_var = f_dt.Compute(function,"");

if (bool.Parse(f_var.ToString()) { do stuff  }
Cevap 21/09/2012 saat 21:55
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more