5

Evalのように数学を実行できるvb.netの文字列(組み込みメソッドなど)を解析する方法はありますか?たとえば、文字列としての3+(7 / 3.5)は2を返します。

私はあなたにこれをコーディングするように求めているのではありません。これを行うための組み込みの方法があるかどうかを知りたいだけです。ない場合は自分でコーディングします。

Sin(90)のようなものをそれ自体で解析することはできないだろうと賭けることができ、それをMath.Sin(90)に置き換える必要があることを理解しています。

組み込みのメソッドがある場合、どのように使用しますか?

4

6 に答える 6

15

DataTable.Computeメソッドを使用して、限定された(つまり単純な)数式のショートカットがあります。明らかに、これは堅牢ではなく(機能が制限されている)、この目的でDataTableを悪用するのはハックだと感じますが、現在の回答に追加すると思いました。

例:

var result = new DataTable().Compute("3+(7/3.5)", null); // 5

「Sin(90)」はこのアプローチでは機能しません。サポートされている関数のリストについては、特に「集計」セクションの下にあるDataColumn.Expressionプロパティページを参照してください。

System.CodeDom名前空間の使用はオプションです。

いくつかの役立つリンク:


編集:あなたのコメントに対処するために、三角関数を同等の数学クラスのメソッドに置き換えることを示すアプローチがあります。

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」グループの内容を知っておく必要があることに注意してください。私はそれらがintであることを知っているので、それらにInt32.Parseを使用しました。それらがアイテムの組み合わせである場合、この単純なアプローチは機能しません。サポートされていない関数呼び出しで複雑になりすぎた場合は、ソリューションを常にバンドエイドする必要があると思います。その場合は、CodeDomアプローチなどの方が適している可能性があります。

于 2009-09-21T00:01:47.547 に答える
3

これは、他のどこにも言及されていない式を評価する方法です。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
于 2014-09-14T10:11:06.327 に答える
0

少し遅れていますが、これがまさにあなたが望んでいたことです(入力を解析して、'something + 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
于 2010-08-07T09:16:08.470 に答える
0

このCodeProjectの記事はトリックを行うかもしれません:

VB.NETで記述された式エバリュエーター
http://www.codeproject.com/KB/vb/expression_evaluator.aspx

これもあります:http:
//www.dotnetspider.com/resources/2518-mathematical-expression-expression-evaluate-VB.aspx

于 2009-09-20T23:18:14.713 に答える
0

1つの方法は、CodeDom名前空間を使用してコンパイルし、リフレクションを使用して実行することです。そのパフォーマーではないかもしれません、私は知りません。

于 2009-09-20T23:36:23.197 に答える
-1

組み込みのVB.netについてはわかりませんが、IronPythonランタイムにリンクして式を渡すことで、このようなことを行います。これは、リフレクションを使用するよりもはるかに高速です。

于 2009-09-20T23:12:54.100 に答える