Deutsch
Forum

Probleme mit Matheparser (heul!)

 

Jac
de
Lad
Hallo Community. Ich schreibe grad an einem Matheparser. Leider scheitere ich an folgender Situation (Quelltext unten): Der Parser berechnet alles richtig, aber bei der Zahl 1087 berechnet er 7 aus dem String (probierts mal aus!). Es muss an der Prozedur GetBefore liegen, denn die gibt als Startbuchstaben für die Zahl 4 zurück, müsste aber 1 zurückgeben. Kann mir jemand helfen? (Jemand der viel Zeit hat, denn der Quelltext ist äußerst experimentell, nicht kommentiert und gibt bis jetzt Unmengen von Debug-Infos aus, vielle kanns ja mal jemand ausprobieren, Feedback, auch Fragen, wär mir hilfreich, ichsitze jetzt nämlich schon Stunden an dem Problem)!
KompilierenMarkierenSeparieren
declare y1%,y2%

proc Operator

    Parameters f$
    declare a%

    whileloop 5

        if Instr(Mid$("+-*/^",&Loop,1),f$)

            inc a%
            Break

        endif

    wend

    Return a%

endproc

proc GetBefore

    Parameters b$,r%
    Print "Durchsuche ",b$
    y1%=r%-1

    while And(InStr(Mid$(b$,y1%,1),".9876543210"),GT(y1%,1))

        Dec y1%

    wend

    Return Val(Mid$(b$,y1%,2))

endproc

proc GetAfter

    Parameters b$,r%
    y2%=r%+1

    while Instr(Mid$(b$,y2%,1),".9876543210")

        Inc y2%

    wend

    Return Val(Mid$(b$,r%+1,y2%-r%))

endproc

proc Parse

    Parameters fx$
    declare z$,y$,d%,c%,x$,xl%,erg$,a%,erg!,x1!,x2!,in%
    fx$=Translate$(Translate$(Translate$(Translate$(Translate$(Translate$(fx$,",","."),"{","("),"[","("),"}",")"),"]",")")," ","")
    Print "Optimierte Formel: "+fx$
    Noch abfragen ob Anz("(")=Anz(")")!!!

    while Instr("(",fx$)

        d%=Len(fx$)

        while Neq$("(",Mid$(fx$,d%,1))

            Dec d%

        wend

        x$=Right$(fx$,Len(fx$)-d%)
        x$=Left$(x$,Instr(")",x$))
        xl%=Len(x$)
        x$=Del$(x$,Len(x$),1)

        if Operator(x$)

            Print "Parse "+x$+"..."

            whileloop 5

                in%=Instr(Mid$("^*/+-",&Loop,1),x$)
                c%=&Loop

                while in%

                    a%=in%
                    x1!=GetBefore(x$,a%)
                    x2!=GetAfter(x$,a%)

                    if Equ(c%,1)

                        Print "Potenz"
                        erg!=x1!^x2!

                    elseif Equ(c%,2)

                        Print "Mal"
                        erg!=x1!*x2!

                    elseif Equ(c%,3)

                        Print "Durch"
                        erg!=x1!/x2!

                    elseif Equ(c%,4)

                        Print "Plus"
                        erg!=x1!+x2!

                    else

                        Print "Minus"
                        erg!=x1!-x2!

                    endif

                    y$=Del$(x$,1,y2%-1)
                    z$=If(Equ(y1%,1),"",Left$(x$,y1%-1))
                    x$=z$+Str$(erg!)+y$
                    Print Str$(x1!)+","+Str$(x2!)+"="+Str$(erg!)
                    Print "Neue Teilformel: "+x$
                    in%=Instr(Mid$("^*/+-",c%,1),x$)
                    waitinput

                wend

            wend

        endif

        fx$=Left$(fx$,d%-1)+Str$(erg!)+Right$(fx$,Len(fx$)-d%-xl%)
        Print "Neue Formel: "+fx$

    wend

    Return fx$

endproc

declare s$
cls
s$="(((3+5)*2+3*(12+345))+12)"
Print "Formel: "+s$
Print "Ergebnis: "+Parse(s$)
waitinput

Jac
 
Profan² 2.6 bis XProfan 11.1+XPSE+XPIA+XPRR (und irgendwann XIDE)
Core2Duo E8500/T2250, 8192/1024 MB, Radeon HD4850/Radeon XPress 1250, Vista64/XP
08.02.2006  
 




Michael
Wodrich
Du solltest versuchen, das Ganze mit Bleistift und Papier nachzuvollziehen. SEI DER COMPUTER.

Hier Dein Code mit Kommentaren und nachfolgend die schrittweise Auflösung des Programmes (jedenfalls die wichtigen Schritte).
KompilierenMarkierenSeparieren
Declare Y1%,Y2%

Proc Operator

    Parameters F$
    Declare A%

    Whileloop 5

        If Instr(Mid$("+-*/^",&Loop,1),F$)

            Inc A%
            Break

        Endif

    Wend

    Return A%
    *** zeigt, wieviele unterschiedliche Operatoren vorhanden sind
    *** ermittelt aber nicht, wieviele Operatoren insgesamt da sind
    *** (jeder Operator wird nur einmal (als erstes Vorkommen) gezählt

Endproc

Proc Getbefore

    Parameters B$,R%
    Print "Durchsuche ",B$
    Y1% = R% - 1

    While And(Instr(Mid$(B$,Y1%,1),".9876543210"),Gt(Y1%,1))

        *** Abbruchbedingung "Y1% > 1" sollte VOR "Mid$(..,Y1%,..)" stehen.
        *** (auch der Eintritt in die Schleife muß beachtet werden: was, wenn Y1% = 0 am Anfang)
        Dec Y1%

    Wend

    Return Val(Mid$(B$,Y1%,2))
    *** FEHLER: die Länge von Mid$ steht fest auf 2
    *** Außderdem wird Y1% auf ein Zeichen vor der ersten Ziffer oder auf Pos.1 stehen

Endproc

Proc Getafter

    Parameters B$,R%
    Y2% = R% + 1

    While Instr(Mid$(B$,Y2%,1),".9876543210")

        *** Ein String ist irgendwann mal zu Ende: ABFANGEN (B$)
        *** (Microsoft patcht immer noch an seinen programmierten Pufferüberläufen herum.)
        *** (Das hätten sie sich gespart, wenn sie immer alle Sonderfälle abgefangen hätten.)
        Inc Y2%

    Wend

    Return Val(Mid$(B$,R%+1,Y2%-R%))
    *** Probe:
    *** B$ = "(12+345"
    *** R% = 4
    *** Y2% = 8
    *** Val( Mid$("(12+345",5,4) ) == 345 ** ABER: es wurde 1 Stelle zuviel berechnet (4)

Endproc

Proc Parse

    Parameters Fx$
    Declare Z$,Y$,D%,C%,X$,Xl%,Erg$,A%,Erg!,X1!,X2!,In%
    *** die folgenden Translates sehen bei mir wunderschön eingerückt aus
    *** und die Parameter dann wieder ausgerückt - war sehr übersichtlich  ;-(
    Fx$ = Translate$(
    Translate$(
    Translate$(
    Translate$(
    Translate$(
    Translate$(Fx$,",","."),   wandle Komma in Punkt
    "{","("),   wandle geschweifte Klammer in runde K.
    "[","("),   wandle eckige K. in runde K.
    "}",")"),   wandle geschweifte Klammer in runde K.
    "]",")"),   wandle eckige K. in runde K.
    " ","")  entferne alle Leerzeichen
    Print "Optimierte Formel: "+Fx$
    Noch abfragen ob Anz("(")=Anz(")")!!!
    ***   If NEq(
    ***          ( Len(Fx$) - Len(Translate$(Fx$,"(","")) ),
    ***          ( Len(Fx$) - Len(Translate$(Fx$,")","")) )
    ***         )
    ***     Teletubby_Modus(ein)
    ***       say "ohh-ohhh"
    ***     Teletubby_Modus(aus)
    ***   EndIf

    While Instr("(",Fx$)

        *** ohne Klammern macht der Parser dicke Backen...
        D% = Len(Fx$)

        While Neq$("(",Mid$(Fx$,D%,1))

            Dec D%

        Wend

        X$ = Right$(Fx$,Len(Fx$)-D%)
        X$ = Left$(X$,Instr(")",X$))
        Xl% = Len(X$)
        X$ = Del$(X$,Len(X$),1)

        If Operator(X$)

            Print "Parse "+X$+"..."

            Whileloop 5

                In%=Instr(Mid$("^*/+-",&Loop,1),X$)
                C%=&Loop

                While In%

                    A% = In%
                    X1! = Getbefore(X$,A%)
                    X2! = Getafter(X$,A%)

                    If Equ(C%,1)

                        Print "Potenz"
                        Erg! = X1! ^ X2!

                    Elseif Equ(C%,2)

                        Print "Mal"
                        Erg! = X1! * X2!

                    Elseif Equ(C%,3)

                        Print "Durch"
                        Erg! = X1! / X2!

                    Elseif Equ(C%,4)

                        Print "Plus"
                        Erg! = X1! + X2!

                    Else

                        Print "Minus"
                        Erg! = X1! - X2!

                    Endif

                    Y$ = Del$(X$,1,Y2%-1)
                    Z$ = If(Equ(Y1%,1),"",Left$(X$,Y1%-1))
                    X$ = Z$ + Str$(Erg!) + Y$
                    Print Str$(X1!) + "," + Str$(X2!) + "=" + Str$(Erg!)
                    Print "Neue Teilformel: "+X$
                    In% = Instr(Mid$("^*/+-",C%,1),X$)
                    Waitinput

                Wend

            Wend

        Endif

        Fx$ = Left$(Fx$,D%-1) + Str$(Erg!) + Right$(Fx$,Len(Fx$)-D%-Xl%)
        Print "Neue Formel: "+Fx$

    Wend

    Return Fx$

Endproc

Declare S$
Cls
S$ = "(((3+5)*2+3*(12+345))+12)"
Print "Formel: "+S$
Print "Ergebnis: "+Parse(S$)
Waitinput
End

Und nun im Pseudo-Code nachvollziehen:

Fx$ = (((3+5)*2+3*(12+345))+12)

(((3+5)*2+3*(12+345))+12)
........................^
D% = 25

(((3+5)*2+3*(12+345))+12)
............^
D% = 13

X$ = (12+345))+12)
X$ = (12+345)
X1% = 8
X$ = (12+345
A% = 4

X1! = GetBefore( (12+345, 4 ) ** ist das so gewollt? Val() löst Fehler aus und liefert 0
Y1% = 1
X1! = 0.0

X2! = GetAfter( (12+345, 4 )
Y2% = 8
X2! = 345.0
Erg! = 345.0

Y$ =
Z$ =
X$ = 345.0000

Print: 0.0000,345.0000=345.0000
Print: Neue Teilformel: 345.0000

Fx$ = (((3+5)*2+3*345.0000+12)
Print: Neue Formel: (((3+5)*2+3*345.0000+12)

(((3+5)*2+3*345.0000+12)
....................^ ** hier fehlt jetzt eine schließende Klammer
...
... usw.


Es kann natürlich sein, daß ich mich da verhaspelt habe. Ein Papiercomputer (so nennt man diese Herangehensweise) ist natürlich nur so gut wie der Ausführende die Funktionen kennt.

Deine Vermutung hat sich übrigens bestätigt: größter Übeltäter ist das GetBefore().

Schöne Grüße
Michael Wodrich
 
Programmieren, das spannendste Detektivspiel der Welt.
09.02.2006  
 




Jac
de
Lad
Erstmal danke für die Mühe. Mit Papiercomputern kann ich irgendwie nichts anfangen und ich kommentiere schon immer schlecht. Bis jetzt habe ich aber alle Probleme lösen können. Hm, ich probiers mal bei GetBefore mit Neq(Instr(...),0), vielleicht hilft das. Ich melde mich wieder!

Jac
 
Profan² 2.6 bis XProfan 11.1+XPSE+XPIA+XPRR (und irgendwann XIDE)
Core2Duo E8500/T2250, 8192/1024 MB, Radeon HD4850/Radeon XPress 1250, Vista64/XP
09.02.2006  
 




Jac
de
Lad
Oh, verdammt. Hab grad erst gefunden...ich baue erstmal alles um, was du schon angekreidet hast. Schon peinlich wieviele Fehler du auf einmal findest...aber ist auch noch nicht fertig!

Jac
 
Profan² 2.6 bis XProfan 11.1+XPSE+XPIA+XPRR (und irgendwann XIDE)
Core2Duo E8500/T2250, 8192/1024 MB, Radeon HD4850/Radeon XPress 1250, Vista64/XP
09.02.2006  
 




Jac
de
Lad
Oh, verdammt. Hab grad erst gefunden...ich baue erstmal alles um, was du schon angekreidet hast. Schon peinlich wieviele Fehler du auf einmal findest...aber ist auch noch nicht fertig!

Jac
 
Profan² 2.6 bis XProfan 11.1+XPSE+XPIA+XPRR (und irgendwann XIDE)
Core2Duo E8500/T2250, 8192/1024 MB, Radeon HD4850/Radeon XPress 1250, Vista64/XP
09.02.2006  
 




Jac
de
Lad
Hallo Michael!

Danke für die große Hilfe, ich habe alle Fehler gefunden und der Parser läuft jetzt mit den 5 Grundrechenarten (naja, 4 Grundrechenarten plus Potenz) einwandfrei. Ach übrigens: Die Prozedur Operator ermittelt nur, ob es sich beim übergebenen String lediglich um eine Zahl oder einen Term handelt. Mehr nicht. Naja, ich werde das Teil jetzt zuende entwickeln...

Hat überhaupt jemand daran Interesse???

Jac
 
Profan² 2.6 bis XProfan 11.1+XPSE+XPIA+XPRR (und irgendwann XIDE)
Core2Duo E8500/T2250, 8192/1024 MB, Radeon HD4850/Radeon XPress 1250, Vista64/XP
09.02.2006  
 



Wir haben alle Interesse an einer Compute-Funktion!
 
09.02.2006  
 




Jac
de
Lad
Oh, hm...

Naja ich hab heute nachmittag etliche Stunden dran geschrieben. Nur leider ist mir kurz vorm Ende aufgefallen, dass ich negative Zahlen gar nicht betrachtet habe. Also fange ich jetzt nochmal ganz von vorne an! Ich melde mich wieder!

Jac
 
Profan² 2.6 bis XProfan 11.1+XPSE+XPIA+XPRR (und irgendwann XIDE)
Core2Duo E8500/T2250, 8192/1024 MB, Radeon HD4850/Radeon XPress 1250, Vista64/XP
09.02.2006  
 



Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

618 Betrachtungen

Unbenanntvor 0 min.
RudiB.15.04.2020
Peter Max Müller18.05.2018
Michael W.23.12.2016
Julian Schmidt11.09.2012

Themeninformationen

Dieses Thema hat 3 Teilnehmer:

Jac de Lad (6x)
iF (1x)
Michael Wodrich (1x)


Admins  |  AGB  |  Anwendungen  |  Autoren  |  Chat  |  Datenschutz  |  Download  |  Eingangshalle  |  Hilfe  |  Händlerportal  |  Impressum  |  Mart  |  Schnittstellen  |  SDK  |  Services  |  Spiele  |  Suche  |  Support

Ein Projekt aller XProfaner, die es gibt!


Mein XProfan
Private Nachrichten
Eigenes Ablageforum
Themen-Merkliste
Eigene Beiträge
Eigene Themen
Zwischenablage
Abmelden
 Deutsch English Français Español Italia
Übersetzungen

Datenschutz


Wir verwenden Cookies nur als Session-Cookies wegen der technischen Notwendigkeit und bei uns gibt es keine Cookies von Drittanbietern.

Wenn du hier auf unsere Webseite klickst oder navigierst, stimmst du unserer Erfassung von Informationen in unseren Cookies auf XProfan.Net zu.

Weitere Informationen zu unseren Cookies und dazu, wie du die Kontrolle darüber behältst, findest du in unserer nachfolgenden Datenschutzerklärung.


einverstandenDatenschutzerklärung
Ich möchte keinen Cookie