Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB6 > Уравнение в виде строки


Автор: I_Am_Rock 19.3.2008, 20:09
Всем привет!

Я давно где-то в инете видел пример, как решать уравнения, представленные в виде строки.
Например, пользователь вводит строку "1 + (2 *4)" и получает 9.

Никто не знает, как это можно организовать на VB?
Или, может, кто-нибудь может дать ссылки?

Заранее спасибо! smile

Автор: iff 19.3.2008, 21:33
Объявляем функции:
Код

Private Function EvaluateExpr(ByVal expr As String) As Single
On Error Resume Next

Const PREC_NONE = 11
Const PREC_UNARY = 10   ' Not actually used.
Const PREC_POWER = 9
Const PREC_TIMES = 8
Const PREC_DIV = 7
Const PREC_INT_DIV = 6
Const PREC_MOD = 5
Const PREC_PLUS = 4

Dim is_unary As Boolean
Dim next_unary As Boolean
Dim parens As Integer
Dim pos As Integer
Dim expr_len As Integer
Dim ch As String
Dim lexpr As String
Dim rexpr As String
Dim value As String
Dim status As Long
Dim best_pos As Integer
Dim best_prec As Integer

    ' Remove leading and trailing blanks.
    expr = Trim$(expr)
    expr_len = Len(expr)
      
    If expr_len = 0 Then Exit Function

    ' If we find + or - now, it is a unary operator.
    is_unary = True

    ' So far we have nothing.
    best_prec = PREC_NONE

    ' Find the operator with the lowest precedence.
    ' Look for places where there are no open
    ' parentheses.
    For pos = 1 To expr_len
        ' Examine the next character.
        ch = Mid$(expr, pos, 1)

        ' Assume we will not find an operator. In
        ' that case the next operator will not
        ' be unary.
        next_unary = False

        If ch = " " Then
            ' Just skip spaces.
            next_unary = is_unary
        ElseIf ch = "(" Then
            ' Increase the open parentheses count.
            parens = parens + 1

            ' An operator after "(" is unary.
            next_unary = True
        ElseIf ch = ")" Then
            ' Decrease the open parentheses count.
            parens = parens - 1

            ' An operator after ")" is not unary.
            next_unary = False

            ' If parens < 0, too many ')'s.
            If parens < 0 Then
                Err.Raise vbObjectError + 1001, _
                    "EvaluateExpr", _
                    "Too many )s in '" & _
                    expr & "'"
            End If
        ElseIf parens = 0 Then
            ' See if this is an operator.
            If ch = "^" Or ch = "*" Or _
               ch = "/" Or ch = "\" Or _
               ch = "%" Or ch = "+" Or _
               ch = "-" _
            Then
                ' An operator after an operator
                ' is unary.
                next_unary = True
                
                Select Case ch
                    Case "^"
                        If best_prec >= PREC_POWER Then
                            best_prec = PREC_POWER
                            best_pos = pos
                        End If
                    
                    Case "*", "/"
                        If best_prec >= PREC_TIMES Then
                            best_prec = PREC_TIMES
                            best_pos = pos
                        End If
                    
                    Case "\"
                        If best_prec >= PREC_INT_DIV Then
                            best_prec = PREC_INT_DIV
                            best_pos = pos
                        End If
                    
                    Case "%"
                        If best_prec >= PREC_MOD Then
                            best_prec = PREC_MOD
                            best_pos = pos
                        End If
                    
                    Case "+", "-"
                        ' Ignore unary operators
                        ' for now.
                        If (Not is_unary) And _
                            best_prec >= PREC_PLUS _
                        Then
                            best_prec = PREC_PLUS
                            best_pos = pos
                        End If
                End Select
            End If
        End If
        is_unary = next_unary
    Next pos
    
    ' If the parentheses count is not zero,
    ' there's a ')' missing.
    If parens <> 0 Then
        Err.Raise vbObjectError + 1002, _
            "EvaluateExpr", "Missing ) in '" & _
            expr & "'"
    End If
    
    ' Hopefully we have the operator.
    If best_prec < PREC_NONE Then
        lexpr = Left$(expr, best_pos - 1)
        rexpr = Right$(expr, expr_len - best_pos)
        Select Case Mid$(expr, best_pos, 1)
            Case "^"
                'If lexpr <> 0 Then
                EvaluateExpr = _
                    EvaluateExpr(lexpr) ^ _
                    EvaluateExpr(rexpr)
                'Else
                '    EvaluateExpr = 0
                'End If
            Case "*"
                EvaluateExpr = _
                    EvaluateExpr(lexpr) * _
                    EvaluateExpr(rexpr)
            Case "/"
                EvaluateExpr = _
                    EvaluateExpr(lexpr) / _
                    EvaluateExpr(rexpr)
            Case "\"
                EvaluateExpr = _
                    EvaluateExpr(lexpr) \ _
                    EvaluateExpr(rexpr)
            Case "%"
                EvaluateExpr = _
                    EvaluateExpr(lexpr) Mod _
                    EvaluateExpr(rexpr)
            Case "+"
                EvaluateExpr = _
                    EvaluateExpr(lexpr) + _
                    EvaluateExpr(rexpr)
            Case "-"
                EvaluateExpr = _
                    EvaluateExpr(lexpr) - _
                    EvaluateExpr(rexpr)
        End Select
        Exit Function
    End If
    
    ' If we do not yet have an operator, there
    ' are several possibilities:
    '
    ' 1. expr is (expr2) for some expr2.
    ' 2. expr is -expr2 or +expr2 for some expr2.
    ' 3. expr is Fun(expr2) for a function Fun.
    ' 4. expr is a primitive.
    ' 5. It's a literal like "3.14159".
    
    ' Look for (expr2).
    If Left$(expr, 1) = "(" And Right$(expr, 1) = ")" Then
        ' Remove the parentheses.
        EvaluateExpr = EvaluateExpr(Mid$(expr, 2, expr_len - 2))
        Exit Function
    End If
        
    ' Look for -expr2.
    If Left$(expr, 1) = "-" Then
        EvaluateExpr = -EvaluateExpr( _
            Right$(expr, expr_len - 1))
        Exit Function
    End If
    
    ' Look for +expr2.
    If Left$(expr, 1) = "+" Then
        EvaluateExpr = EvaluateExpr( _
            Right$(expr, expr_len - 1))
        Exit Function
    End If
    
    ' Look for Fun(expr2).
    If expr_len > 5 And Right$(expr, 1) = ")" Then
        lexpr = LCase$(Left$(expr, 4))
        rexpr = Mid$(expr, 5, expr_len - 5)
        Select Case lexpr
            Case "sin("
                EvaluateExpr = Sin(EvaluateExpr(rexpr))
                Exit Function
            Case "cos("
                EvaluateExpr = Cos(EvaluateExpr(rexpr))
                Exit Function
            Case "tan("
                EvaluateExpr = Tan(EvaluateExpr(rexpr))
                Exit Function
            Case "atn("
                EvaluateExpr = Atn(EvaluateExpr(rexpr))
                Exit Function
            Case "sqr("
                EvaluateExpr = Sqr(EvaluateExpr(rexpr))
                Exit Function
            Case "log("
                EvaluateExpr = Log(EvaluateExpr(rexpr)) / Log(10)
                Exit Function
            Case "lne("
                EvaluateExpr = Log(EvaluateExpr(rexpr))
                Exit Function
            Case "exp("
                EvaluateExpr = Exp(EvaluateExpr(rexpr))
                Exit Function
            Case "abs("
                EvaluateExpr = Abs(EvaluateExpr(rexpr))
                Exit Function
        End Select
    End If
    
    
    On Error Resume Next
    EvaluateExpr = CSng("0" & expr)
    status = Err.Number
    On Error GoTo 0
    If status <> 0 Then
        Err.Raise status, _
            "EvaluateExpr", _
            "Error evaluating '" & expr & _
            "' as a constant."
    End If
End Function


Выводим сообщение:
Код

MsgBox EvaluateExpr("1 + (2 *4)")


И ещё. Если пример подоёдёт, нен нада затруднять себя сообщениями об этом. Просто повысь репутацию.

Автор: Akina 20.3.2008, 09:45
http://www.rostix.com/vb/code/s5.htm

Автор: daNick 25.3.2008, 10:09
iff, ваш код реализует ПОЛИЗ?

Автор: iff 25.3.2008, 17:50
daNick, Что такое ПОЛИЗ?

Автор: daNick 28.3.2008, 11:20
iff, ПОЛИЗ=ПОЛьская Инверсионная Запись, она же польская нотация или постфиксная нотация... В общем, типа: 2+3*4 ~ 234*+

Автор: iff 28.3.2008, 18:52
daNick, нет, не реализует.

Автор: daNick 29.3.2008, 09:35
iff, в таком случае, позвольте поинтересоваться, как называется алгоритм, который реализует ваша программа?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)