Mã:
//Định nghĩa trên có nghĩa là khai báo sử dụng phần biên dịch mở rộng Extension// Parser cho việc dịch từ xâu biểu thức thành cây nhị phân biểu thức.#define PARSERusing System;using System.Collections.Generic;using System.Text;using ExpressionTree; namespace ExpressionTree{ public enum ExpressionNodeType {UNDEF=-1,OPER,CONST,VAR,FUNC,UNARY}; //Lớp ExpresisonNode cơ bản class ExpressionNode { public ExpressionNodeType NodeType=ExpressionNodeType.UNDEF; public ExpressionNode(){} public override string ToString(){return "";} public virtual double Evaluate(){return Double.NaN;} #if PARSER public static void Normalize(ref string strExpr) { if (String.IsNullOrEmpty(strExpr)) return; //Loại bỏ mọi khoảng trắng trước khi xử lý strExpr = strExpr.Replace(" ", ""); //Bước 1 : Loại bỏ toàn bộ các ngoặc không hợp lệ bằng cách thêm vào đó các ( hoặc ) còn thiếu Stack<int> Parents = new Stack<int>(); for (int i = 0; i < strExpr.Length; i++) { if (strExpr[i] == '(') //Nếu là '(' thì đưa vào Stack Parents.Push(i); else if (strExpr[i] == ')') //Nếu kí tự đang xét là ')' { if (Parents.Count > 0) { if (strExpr[Parents.Peek()] == '(') Parents.Pop(); //Nếu đỉnh stack là '(' thì loại bỏ nó ra vì có 1 cặp () hợp lệ else Parents.Push(i); //Ngược lại thì đưa tiếp vào stack } else Parents.Push(i); } } string tmp = strExpr; while (Parents.Count > 0) { if (strExpr[Parents.Peek()] == '(') tmp += ')'; else tmp = '(' + tmp; Parents.Pop(); } strExpr = tmp; //Bước 2: Tại đây ta có được các xâu đã chuẩn hoá, //Tiến hành thêm dấu * cho dang x(b) for (int i = 1; i < strExpr.Length; i++) if (strExpr[i] == '(') { if (Char.IsDigit(strExpr[i - 1]) || (strExpr[i - 1] == ')')) { strExpr = strExpr.Insert(i, "*"); i++; } else { //Thử tách xem trước ( có phải là tên hàm số hay không //Nếu không phải hàm số int k = i; while ((k > 0) && Char.IsLetter(strExpr[k - 1])) k--; if (k < i) { string sub = strExpr.Substring(k, i - k); bool addMulti = true; for (int j = (int)FunctionNodeType.UNDEF + 1; j < (int)FunctionNodeType.ENDFUNCDEF; j++) if ((j != (int)FunctionNodeType.SEPERATOR) && (String.Compare(sub, ((FunctionNodeType)j).ToString(), true) == 0)) { addMulti = false; break; } if (addMulti) { strExpr = strExpr.Insert(i, "*"); i++; } } } } //Tiến hành thêm dấu * cho dạng (z)b thành (z)*b for (int i = strExpr.Length - 2; i >= 0; i--) if (strExpr[i] == ')') { if ((strExpr[i + 1] == '_') || Char.IsLetterOrDigit(strExpr[i + 1])) strExpr = strExpr.Insert(i + 1, "*"); else if ((strExpr[i + 1] == '(') && (i < strExpr.Length - 2)) if (strExpr[i + 2] != '(') strExpr = strExpr.Insert(i + 1, "*"); } //Bước 3 : Loại bỏ tất cả các ngoặc thừa. (((f(x))) và chỉ giữa lại cặp ngoặc cho Unary (-f) for (int i = 0; i < strExpr.Length - 1; i++) { if ((strExpr[i] == '(') && (strExpr[i + 1] == '(')) for (int j = i + 1; j < strExpr.Length - 1; j++) if ((strExpr[j] == ')') && (strExpr[j + 1] == ')')) { strExpr = strExpr.Remove(j + 1, 1); strExpr = strExpr.Remove(i + 1, 1); i--; } } if (String.IsNullOrEmpty(strExpr)) return; //Loại bỏ ngoặc thừa (str) while ((strExpr[0] == '(') && (strExpr[strExpr.Length - 1] == ')')) { int i = 1; int balance = 1; while (balance != 0) { if (strExpr[i] == '(') balance++; if (strExpr[i] == ')') balance--; i++; } if ((i == strExpr.Length) && (balance == 0)) strExpr = strExpr.Substring(1, i - 2); else break; } } public static ExpressionNode MakeExpression(string strExpr) { if (String.IsNullOrEmpty(strExpr)) { return null; } //Mọi thao tác vào Result ExpressionNode result = null; //Loại bỏ ngoặc thừa (str) while ((strExpr[0] == '(') && (strExpr[strExpr.Length - 1] == ')')) { int i = 1; int balance = 1; while (balance != 0) { if (strExpr[i] == '(') balance++; if (strExpr[i] == ')') balance--; i++; } if ((i == strExpr.Length)&&(balance==0)) strExpr = strExpr.Substring(1, i - 2); else break; } //Xác định xâu đang chứa gì phân tích Top-Down FunctionNodeType funcIdx = FunctionNode.FunctionIndex(strExpr); if (funcIdx != FunctionNodeType.UNDEF) { int len = funcIdx.ToString().Length; string strArgs = strExpr.Substring(len + 1, strExpr.Length - len - 2); string[] args = strArgs.Split(new char[] { ',' }); //Hàm có một biến số if (funcIdx < FunctionNodeType.SEPERATOR) result = new FunctionNode(funcIdx, null, MakeExpression(args[0])); else result = new FunctionNode(funcIdx, MakeExpression(args[0]), MakeExpression(args[1])); } //Xét nếu là hằng số else if (ConstNode.IsContanstName(strExpr)) result = new ConstNode(Double.Parse(strExpr)); //Nếu là biến số else if (VarNode.IsVariableName(strExpr)) result = new VarNode(strExpr); else //Nếu là Unary if (UnaryNode.IsUnaryName(strExpr)) result = new UnaryNode(strExpr[0], MakeExpression(strExpr.Substring(1))); else //Nếu là biểu thức { int oper = BinaryExpressionNode.FindOperator(strExpr); if (oper > -1) { string leftStr = strExpr.Substring(0, oper); string rightStr = strExpr.Substring(oper + 1); result = new BinaryExpressionNode(strExpr[oper], MakeExpression(leftStr), MakeExpression(rightStr)); } } return result; } //Thiết lập giá của biến trong cây nhị phân biểu thức public static void SetVar(ref ExpressionNode root, string VarName, double Value) { if (root == null) return; switch(root.NodeType) { case ExpressionNodeType.VAR: if (String.Compare(VarName, ((VarNode)root).varName, true) == 0) { ((VarNode)root).value = Value; } break; case ExpressionNodeType.CONST: break; case ExpressionNodeType.OPER: SetVar(ref ((BinaryExpressionNode)root).Left,VarName,Value); SetVar(ref ((BinaryExpressionNode)root).Right,VarName,Value); break; case ExpressionNodeType.UNARY: SetVar(ref ((UnaryNode)root).Node, VarName, Value); break; case ExpressionNodeType.FUNC: SetVar(ref ((FunctionNode)root).Left, VarName, Value); SetVar(ref ((FunctionNode)root).Right, VarName, Value); break; } } #endif } //Xây dựng Node hằng số class ConstNode:ExpressionNode { private double value=Double.NaN; public ConstNode(double Value) { this.value = Value; this.NodeType = ExpressionNodeType.CONST; } public override double Evaluate() { return value; } public override string ToString() { string result = ""; if (value < 0) result = "(" + value.ToString() + ")"; else result = value.ToString(); return result; } public static ConstNode MakeConstantNode(double Value) { return new ConstNode(Value); } public ConstNode(string strConst) { value = double.Parse(strConst); NodeType = ExpressionNodeType.CONST; } //Hàm kiểm tra một xâu có phải là biểu diễn một hằng số hay không public static bool IsContanstName(string str) { if (String.IsNullOrEmpty(str)) return false; if (!Char.IsDigit(str[0])) return false; double value = Double.NaN; return Double.TryParse(str, out value); } } //Xây dựng lớp biến số class VarNode : ExpressionNode { public string varName = ""; public double value = double.NaN; public VarNode(string VarName) { if (String.IsNullOrEmpty(VarName)) { Console.WriteLine("Variable must be beging with _ or letter character."); return; } else if (Char.IsPunctuation(VarName[0]) || Char.IsLetter(VarName[0])) { value = Double.NaN; varName = VarName; NodeType = ExpressionNodeType.VAR; } else { Console.WriteLine("Variable must be beging with _ or letter character."); return; } } public VarNode(string VarName, double Value) { if (String.IsNullOrEmpty(VarName)) { Console.WriteLine("Variable must be beging with _ or letter character."); return; } else if (Char.IsPunctuation(VarName[0]) || Char.IsLetter(VarName[0])) { value = Value; varName = VarName; NodeType = ExpressionNodeType.VAR; } else { Console.WriteLine("Variable must be beging with _ or letter character."); return; } } public override string ToString() { return varName; } public override double Evaluate() { return value; } public static VarNode MakeVarNode(string VarName) { return new VarNode(VarName); } public static VarNode MakeVarNode(string VarName,double Value) { return new VarNode(VarName, Value); } //Hàm kiểm tra một xâu nhỏ phải là biểu diễn của biến số hay không public static bool IsVariableName(string str) { if (String.IsNullOrEmpty(str)) return false; if (Char.IsLetter(str[0]) || (str[0] == '_')) { for (int i = 1; i < str.Length; i++) if (!(Char.IsLetterOrDigit(str[i]) || (str[i] == '_'))) return false; return true; } return false; } } //Xây dựng lớp UnaryNode class UnaryNode : ExpressionNode { private char Unary; public ExpressionNode Node = null; public UnaryNode(char unary, ExpressionNode node) { if ((unary != '+') && (unary != '-')) { this.NodeType = ExpressionNodeType.UNDEF; Console.WriteLine("Invalid format for UnaryExpressionNode!"); return; } this.NodeType = ExpressionNodeType.UNARY; this.Unary = unary; this.Node = node; } public static UnaryNode MakeUnaryNode(char unary, ExpressionNode node) { return new UnaryNode(unary,node); } public override string ToString() { string result = Node.ToString(); if (Unary=='-') result="(-"+result+")"; return result; } public override double Evaluate() { double result = Node.Evaluate(); if (Unary == '-') result = -result; return result; } //Hàm kiểm tra một xâu có phải là biểu diễn của Unary hay không public static bool IsUnaryName(string str) { if (String.IsNullOrEmpty(str)) return false; if ((str[0] == '-') || (str[0] == '+')) return true; return false; } }//Xây dựng lớp cho biểu diễn cho hàm số public enum FunctionNodeType {UNDEF=-1,ABS=0, ACOS, ASIN, ATAN, CEIL, COS, DEG, EXP, //Các hàm một đối số FLOOR, FRAC, INT, LN, LOG, PI, RAD, SIN,SQRT,TAN, //Các hàm một đối số SEPERATOR, //Ngăn các các hàm một đối số với hàm 2 đối số MIN, MAX, POW, DIVREM, ROUND, //Hàm hai đối số ENDFUNCDEF, //Kết thúc 2 đối số }; class FunctionNode:ExpressionNode { public FunctionNodeType FunctionType; public ExpressionNode Left=null,Right=null; public override string ToString() { string result = ""; //Với các hàm có 1 đối số if (FunctionType == FunctionNodeType.PI) result = "pi()"; else if ((int)FunctionType <= (int)FunctionNodeType.TAN) result = FunctionType.ToString().ToLower() + "(" + Right.ToString() + ")"; else result = FunctionType.ToString().ToLower() + "(" + Left.ToString() + "," + Right.ToString() + ")"; return result; } public FunctionNode(FunctionNodeType function, ExpressionNode left, ExpressionNode right) { if ((int)function < (int)FunctionNodeType.SEPERATOR) { if ((right == null)&&(function!=FunctionNodeType.PI)) { Console.WriteLine("Parameters must be specified."); return; } this.Left = null; this.Right = right; if (function == FunctionNodeType.PI) this.Right = null; this.NodeType = ExpressionNodeType.FUNC; this.FunctionType = function; } else if (((int)function>(int)FunctionNodeType.SEPERATOR)&&((int)function<(int)FunctionNodeType.ENDFUNCDEF)) { if (right == null) { Console.WriteLine("Two paramets in function must be specified"); return; } this.NodeType = ExpressionNodeType.FUNC; this.FunctionType = function; this.Left = left; this.Right = right; } } public FunctionNode(string funcName, ExpressionNode left, ExpressionNode right) { funcName = funcName.ToUpper(); FunctionNodeType function=FunctionNodeType.UNDEF; for (int i=(int)FunctionNodeType.UNDEF+1;i<(int)(FunctionNodeType.ENDFUNCDEF);i++) if (((FunctionNodeType)(i)).ToString().Equals(funcName)) { function = (FunctionNodeType)i; break; } if (((int)function>(int)FunctionNodeType.UNDEF)&& ((int)function<(int)FunctionNodeType.SEPERATOR)) { if ((right == null) && (function != FunctionNodeType.PI)) { Console.WriteLine("Parameters must be specified."); return; } this.Left = null; this.Right = right; this.NodeType = ExpressionNodeType.FUNC; this.FunctionType = function; } else { if (right == null) { Console.WriteLine("Two paramets in function must be specified"); return; } this.NodeType = ExpressionNodeType.FUNC; this.FunctionType = function; this.Left = left; this.Right = right; } } public static FunctionNode MakeFunctionNode(FunctionNodeType function, ExpressionNode left, ExpressionNode right) { return new FunctionNode(function, left, right); } public static FunctionNode MakeFunctionNode(string funcName, ExpressionNode left, ExpressionNode right) { return new FunctionNode(funcName, left, right); } public override double Evaluate() { double result = Double.NaN; switch (FunctionType) { case FunctionNodeType.ABS: result = Math.Abs(Right.Evaluate()); break; case FunctionNodeType.ACOS: result=Math.Cos(Right.Evaluate()); break; case FunctionNodeType.ASIN: result = Math.Asin(Right.Evaluate()); break; case FunctionNodeType.ATAN: result = Math.Atan(Right.Evaluate()); break; case FunctionNodeType.CEIL: result = Math.Ceiling(Right.Evaluate()); break; case FunctionNodeType.COS: result = Math.Cos(Right.Evaluate()); break; case FunctionNodeType.DEG: result = Right.Evaluate() / Math.PI * 180; break; case FunctionNodeType.DIVREM: result=Math.IEEERemainder(Left.Evaluate(),Right.Evaluate()); break; case FunctionNodeType.EXP: result = Math.Exp(Right.Evaluate()); break; case FunctionNodeType.FLOOR: result = Math.Floor(Right.Evaluate()); break; case FunctionNodeType.FRAC: double eval=Right.Evaluate(); result = eval - (int)eval; break; case FunctionNodeType.INT: result = Math.Truncate(Right.Evaluate()); break; case FunctionNodeType.LN: result = Math.Log(Right.Evaluate()); break; case FunctionNodeType.LOG: result = Math.Log10(Right.Evaluate()); break; case FunctionNodeType.MAX: result = Math.Max(Left.Evaluate(), Right.Evaluate()); break; case FunctionNodeType.MIN: result = Math.Min(Left.Evaluate(), Right.Evaluate()); break; case FunctionNodeType.PI: result = Math.PI; break; case FunctionNodeType.POW: result = Math.Pow(Left.Evaluate(), Right.Evaluate()); break; case FunctionNodeType.ROUND: result = Math.Round(Left.Evaluate(), (int)Right.Evaluate()); break; case FunctionNodeType.RAD: result = Math.PI * Right.Evaluate() / 180; break; case FunctionNodeType.SIN: result = Math.Sin(Right.Evaluate()); break; case FunctionNodeType.SQRT: result = Math.Sqrt(Right.Evaluate()); break; case FunctionNodeType.TAN: result = Math.Tan(Right.Evaluate()); break; case FunctionNodeType.UNDEF: result = Double.NaN; break; } return result; } #if PARSER //Hàm kiểm tra một xâu strExpr có là dạng của Hàm(...) hay không public static FunctionNodeType FunctionIndex(string strExpr) { if (String.IsNullOrEmpty(strExpr)) return FunctionNodeType.UNDEF; for (int i = (int)FunctionNodeType.ABS; i < (int)FunctionNodeType.ENDFUNCDEF; i++) if (i != (int)FunctionNodeType.SEPERATOR) { string orgFuncName = ((FunctionNodeType)i).ToString(); int len = Math.Min(orgFuncName.Length, strExpr.Length); if (len == strExpr.Length) continue; else { string extractFuncName = strExpr.Substring(0, len); if ((String.Compare(orgFuncName, extractFuncName, true) == 0) && (strExpr[len] == '(')) { int j = len + 1; int balance = 1; while ((j < strExpr.Length) && (balance != 0)) { if (strExpr[j] == '(') balance++; if (strExpr[j] == ')') balance--; j++; } if ((j == strExpr.Length) && (balance == 0)) return (FunctionNodeType)i; } } } return FunctionNodeType.UNDEF; } #endif } //Xây dựng lớp BinaryExpression cũng chính là lớp cây nhị phân biểu thức của ta class BinaryExpressionNode:ExpressionNode { public ExpressionNode Left = null, Right = null; public char Oper; public BinaryExpressionNode(char oper, ExpressionNode left, ExpressionNode right) { if ((left == null) || (right == null)) { this.Oper = oper; this.Left = this.Right = null; Console.WriteLine("Binary Expression Node parameter is invalid."); return; } if ((oper=='+')||(oper=='-')||(oper=='*')||(oper=='/')||(oper=='^')||(oper=='%')) { //Normal Expression Node this.Oper = oper; this.NodeType = ExpressionNodeType.OPER; this.Left = left; this.Right = right; } } public static BinaryExpressionNode MakeBinaryExpression(char oper, ExpressionNode left, ExpressionNode right) { BinaryExpressionNode result = null; try { result= new BinaryExpressionNode(oper, left, right); } catch (FormatException e) { Console.WriteLine(e); } return result; } public override string ToString() { return TreeToString(this); } private static string TreeToString(ExpressionNode root) { string result=""; if (root != null) { switch (root.NodeType) { case ExpressionNodeType.OPER: BinaryExpressionNode t1 = (BinaryExpressionNode)root; result = "(" + TreeToString(t1.Left) + t1.Oper.ToString() + TreeToString(t1.Right) + ")"; break; case ExpressionNodeType.CONST: ConstNode t2 = (ConstNode)root; result = t2.ToString(); break; case ExpressionNodeType.FUNC: FunctionNode t3 = (FunctionNode)root; result = t3.ToString(); break; case ExpressionNodeType.UNARY: UnaryNode t4 = (UnaryNode)(root); result = t4.ToString(); break; case ExpressionNodeType.VAR: VarNode t5 = (VarNode)root; result = t5.ToString(); break; } } return result; } public override double Evaluate() { double result = double.NaN; switch (Oper) { case '-': result = Left.Evaluate() - Right.Evaluate(); break; case '+': result = Left.Evaluate() + Right.Evaluate(); break; case '*': result = Left.Evaluate() * Right.Evaluate(); break; case '/': try { result = Left.Evaluate() / Right.Evaluate(); } catch (DivideByZeroException e) { Console.WriteLine(e.Message); result = Double.NaN; } break; case '^': result = Math.Pow(Left.Evaluate(), Right.Evaluate()); break; case '%': try { long ret = 0; Math.DivRem((long)Left.Evaluate(),(long)Right.Evaluate(),out ret); result = ret; } catch(DivideByZeroException e) { Console.WriteLine(e.Message); result=Double.NaN; } break; } return result; } #if PARSER public static int FindOperator(string strExpr) { int position = -1; int Min = int.MaxValue; int add = 0; for (int i = strExpr.Length-1; i>=1; i--) { switch (strExpr[i]) { case '-': case '+': //Không phải toán tử Unary if ((strExpr[i - 1] != '(') && (add + 1 < Min)) { position = i; Min = add + 1; } break; case '/': case '*': if (add + 2 < Min) { position = i; Min = add + 2; } break; case '%': if (add + 3 < Min) { position = i; Min = add + 3; } break; case '^': if (add + 4 < Min) { position = i; Min = add + 4; } break; case '(': add -= 5; break; case ')': add += 5; break; } } return position; } #endif } class Program { static void Main(string[] args) { while (true) { //Nhập xâu từ bàn phím Console.Clear(); Console.WriteLine("Enter Expression : "); string strExpr = Console.ReadLine(); if ((String.Compare(strExpr, "quit", true) == 0) || (String.Compare(strExpr, "exit", true) == 0)) break; if (!String.IsNullOrEmpty(strExpr)) { //Chuẩn hoá xâu sau khi nhập và trước khi dịch thành cây ExpressionNode.Normalize(ref strExpr); ExpressionNode root = ExpressionNode.MakeExpression(strExpr); //Thiết lập giá trị biến x là 1 trong cây nhị phân biểu thức ExpressionNode.SetVar(ref root, "x", 1); //Thực hiện việc tính giá trị biểu thức và in ra màn hình Console.WriteLine("Result : "+root.Evaluate()); Console.WriteLine("Expression : "+root.ToString()); Console.ReadKey(); } } } }}
Ngọc Bích xanh bản chất thuộc dòng đá đá hoa (jade). Và cẩm thạch là tên gọi chung của ngọc bích. Vì thực chất chúng thuộc dòng đá đa khoáng được hình thành từ chất Silicat dưới dạng dioxy. Ngọc bích...
Chia sẻ Vòng tay ngọc bích xanh là...