有什么办法来解析在vb.net(如,内置的方法)的字符串,可以做数学题一样评估和演示可以吗? 例如,3 +(7 / 3.5)作为字符串将返回2。
我不要求你为我编写这个,我只是想知道是否有一个内置的方式做到这一点,如果没有,我会编写它自己。
我可以下注,这将无法在其自己的解析类的东西仙(90),据我所知,需要由Math.Sin(90)来代替。
如果有一个内置的方法,你如何使用它?
有什么办法来解析在vb.net(如,内置的方法)的字符串,可以做数学题一样评估和演示可以吗? 例如,3 +(7 / 3.5)作为字符串将返回2。
我不要求你为我编写这个,我只是想知道是否有一个内置的方式做到这一点,如果没有,我会编写它自己。
我可以下注,这将无法在其自己的解析类的东西仙(90),据我所知,需要由Math.Sin(90)来代替。
如果有一个内置的方法,你如何使用它?
还有的限制(即简单)数学通过使用表达式的快捷DataTable.Compute方法 。 显然,这是不稳健(有限功能),感觉hackish的滥用DataTable中用于此目的,但我想我会添加到当前的答案。
例:
var result = new DataTable().Compute("3+(7/3.5)", null); // 5
“仙(90)”不会用这种方式工作。 请参阅DataColumn.Expression属性页有关支持的函数列表,特别是“聚集”部分。
使用System.CodeDom命名空间是一个选项。
一些有用的链接:
编辑:解决您的评论,这里是展示他们的等价Math类方法代替三角函数的方法。
C#
string expression = "(Sin(0) + Cos(0)+Tan(0)) * 10";
string updatedExpression = Regex.Replace(expression, @"(?<func>Sin|Cos|Tan)\((?<arg>.*?)\)", match =>
match.Groups["func"].Value == "Sin" ? Math.Sin(Int32.Parse(match.Groups["arg"].Value)).ToString() :
match.Groups["func"].Value == "Cos" ? Math.Cos(Int32.Parse(match.Groups["arg"].Value)).ToString() :
Math.Tan(Int32.Parse(match.Groups["arg"].Value)).ToString()
);
var result = new DataTable().Compute(updatedExpression, null); // 10
VB.NET
Dim expression As String = "(Sin(0) + Cos(0)+Tan(0)) * 10"
Dim updatedExpression As String = Regex.Replace(expression, "(?<func>Sin|Cos|Tan)\((?<arg>.*?)\)", Function(match As Match) _
If(match.Groups("func").Value = "Sin", Math.Sin(Int32.Parse(match.Groups("arg").Value)).ToString(), _
If(match.Groups("func").Value = "Cos", Math.Cos(Int32.Parse(match.Groups("arg").Value)).ToString(), _
Math.Tan(Int32.Parse(match.Groups("arg").Value)).ToString())) _
)
Dim result = New DataTable().Compute(updatedExpression, Nothing)
但是请注意,你需要知道“ARG”组的内容。 我知道他们是整数,所以我用Int32.Parse他们。 如果他们是项目的组合,然后这个简单的方法是行不通的。 我怀疑你会经常需要创可贴的解决方案,如果它变得太复杂,更不支持的函数调用,在这种情况下,CodeDOM的方法或其他人可能更适合。
这里有一个方法来评估,我还没有看到提到其他地方的表达式:使用WebBrowser
控件和JavaScript的eval()
Option Strict On
Imports System.Security.Permissions
<PermissionSet(SecurityAction.Demand, Name:="FullTrust")> _
<System.Runtime.InteropServices.ComVisibleAttribute(True)>
Public Class Form1
Dim browser As New WebBrowser
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
browser.ObjectForScripting = Me
'browser.ScriptErrorsSuppressed = True
browser.DocumentText = "<script>function evalIt(x) { return eval(x); }</script>"
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim result = browser.Document.InvokeScript("evalIt", New String() {"3+4*5"})
If result IsNot Nothing Then
MessageBox.Show(result.ToString()) '23
End If
End Sub
End Class
这CodeProject上的文章可能做的伎俩:
写在VB.NET表达式评估
http://www.codeproject.com/KB/vb/expression_evaluator.aspx
也有这样的:
http://www.dotnetspider.com/resources/2518-mathematical-expression-expression-evaluate-VB.aspx
我不知道VB.net内置的,但我们在IronPython的运行链接和传递表达做这样的东西。 这是使用反射的方式方法更快。
一种方法是使用的CodeDOM命名空间来编译它,使用反射执行它。 可能不是高性能的,我不知道。
这是一个有点晚了,但在这里就是你想要的到底是什么(请确保您解析输入以确保有没有像陈述“的东西+ vbcrlf + EXEC‘FORMAT C:’”在里面):
用法:
MessageBox.Show(COR.Tools.EvalProvider.Eval("return 8-3*2").ToString())
类:
'Imports Microsoft.VisualBasic
Imports System
Namespace COR.Tools
Public Class EvalProvider
Public Shared Function Eval(ByVal vbCode As String) As Object
Dim c As VBCodeProvider = New VBCodeProvider
Dim icc As System.CodeDom.Compiler.ICodeCompiler = c.CreateCompiler()
Dim cp As System.CodeDom.Compiler.CompilerParameters = New System.CodeDom.Compiler.CompilerParameters
cp.ReferencedAssemblies.Add("System.dll")
cp.ReferencedAssemblies.Add("System.xml.dll")
cp.ReferencedAssemblies.Add("System.data.dll")
' Sample code for adding your own referenced assemblies
'cp.ReferencedAssemblies.Add("c:\yourProjectDir\bin\YourBaseClass.dll")
'cp.ReferencedAssemblies.Add("YourBaseclass.dll")
cp.CompilerOptions = "/t:library"
cp.GenerateInMemory = True
Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder("")
sb.Append("Imports System" & vbCrLf)
sb.Append("Imports System.Xml" & vbCrLf)
sb.Append("Imports System.Data" & vbCrLf)
sb.Append("Imports System.Data.SqlClient" & vbCrLf)
sb.Append("Imports Microsoft.VisualBasic" & vbCrLf)
sb.Append("Namespace MyEvalNamespace " & vbCrLf)
sb.Append("Class MyEvalClass " & vbCrLf)
sb.Append("public function EvalCode() as Object " & vbCrLf)
'sb.Append("YourNamespace.YourBaseClass thisObject = New YourNamespace.YourBaseClass()")
sb.Append(vbCode & vbCrLf)
sb.Append("End Function " & vbCrLf)
sb.Append("End Class " & vbCrLf)
sb.Append("End Namespace" & vbCrLf)
Debug.WriteLine(sb.ToString()) ' look at this to debug your eval string
Dim cr As System.CodeDom.Compiler.CompilerResults = icc.CompileAssemblyFromSource(cp, sb.ToString())
Dim a As System.Reflection.Assembly = cr.CompiledAssembly
Dim o As Object
Dim mi As System.Reflection.MethodInfo
o = a.CreateInstance("MyEvalNamespace.MyEvalClass")
Dim t As Type = o.GetType()
mi = t.GetMethod("EvalCode")
Dim s As Object
s = mi.Invoke(o, Nothing)
Return s
End Function
End Class ' EvalProvider
End Namespace