[C#]計算以字串表示的數學運算式結果
2010/12/03 小朱推薦的 NCalc 很不錯,參考 NCalc: 處理數學運算的好幫手
一、問題描述
當有個數學運算式以 string 變數表示,例如
string str = "91 + 91 * 100";
如何計算此數學運算式的結果
二、方法
可以實現的方式相當多,在此文提供兩種方法
方法 1 : 使用 ScriptControl 調用 VBScript 進行計算
首先將 Microosft Script Control 1.0 加入參考,在專案的參考上按滑鼠右鍵,選擇 [加入參考],切換到 [COM] 索引標籤,找出 Microosft Script Control 1.0 按 [確定]。
範例程式碼
/// <summary>
/// 使用 ScriptControl 與 VBScript
/// </summary>
/// <param name="sExpression">數值運算式</param>
/// <returns>數值運算結果</returns>
public static double EvaluateUsingScriptControl(string sExpression)
{
MSScriptControl.ScriptControl sc = new MSScriptControl.ScriptControl();
sc.Language = "VBScript";
return double.Parse(sc.Eval(sExpression).ToString());
}
方法 2 : 使用 XPathNavigator.Evaluate 進行計算
XPathNavigator.Evaluate 方法 (XPathExpression) : 評估 XPathExpression,並傳回具型別的結果。
命名空間: System.Xml.XPath
組件: System.Xml (在 system.xml.dll 中)
參數
expr
可以接受評估的 XPathExpression。
傳回值
運算式的結果 (布林值、數字、字串或節點集)。這會分別對應至 Boolean、Double、String 或 XPathNodeIterator 等物件。
要使用 XPathNavigator.Evaluate,必須先將運算式修改為 XPathExpression,此部分透過 regex 處理
範例程式碼
/// <summary>
/// 使用 XPathDocument
/// </summary>
/// <param name="sExpression">數值運算式</param>
/// <returns>數值運算結果</returns>
public static double EvaluateUsingXPathDocument(string sExpression)
{
var xsltExpression = string.Format("number({0})",
new Regex(@"([\+\-\*])").Replace(sExpression, " ${1} ")
.Replace("/", " div ")
.Replace("%", " mod "));
return (double)new XPathDocument(new StringReader("<r/>")).CreateNavigator().Evaluate(xsltExpression);
}
三、示範
程式碼下載 WinFormsEval.zip
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.XPath;
using System.IO;
using System.Text.RegularExpressions;
namespace WinFormsEval
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnEvaluate_Click(object sender, EventArgs e)
{
string sExpression = this.txtExpression.Text.Trim();
if (sExpression.Length == 0) return;
MessageBox.Show(EvaluateUsingScriptControl(sExpression).ToString(), "Evaluate Using ScriptControl");
MessageBox.Show(EvaluateUsingXPathDocument(sExpression).ToString(), "Evaluate Using XPathDocument");
this.txtExpression.Clear();
}
/// <summary>
/// 使用 ScriptControl 與 VBScript
/// </summary>
/// <param name="sExpression">數值運算式</param>
/// <returns>數值運算結果</returns>
public static double EvaluateUsingScriptControl(string sExpression)
{
MSScriptControl.ScriptControl sc = new MSScriptControl.ScriptControl();
sc.Language = "VBScript";
return double.Parse(sc.Eval(sExpression).ToString());
}
/// <summary>
/// 使用 XPathDocument
/// </summary>
/// <param name="sExpression">數值運算式</param>
/// <returns>數值運算結果</returns>
public static double EvaluateUsingXPathDocument(string sExpression)
{
var xsltExpression = string.Format("number({0})",
new Regex(@"([\+\-\*])").Replace(sExpression, " ${1} ")
.Replace("/", " div ")
.Replace("%", " mod "));
return (double)new XPathDocument(new StringReader("<r/>")).CreateNavigator().Evaluate(xsltExpression);
}
}
}
四、相關參考與連結
MSDN 論壇 - 如何在vb中求出由若干变量组成的算数表达式的结果?
Is it possible to translate a user-entered mathematical equation into C# code at runtime?