Volker Nebelung: Einen String mathematisch auswerten

Hallo zusammen,

ich habe folgendes Problem: Ich habe einen Satz von Zahlen und mathematischen Verknüpfungen (in diesem Fall + , * und =) und deren jeweilige Anzahl.
Alle möglichen Anordnungen dieses Alphabets will ich nun per Brutforce auswerten, ob diese Sinn machen, z.B.:
123+= ... 1=+32 ... 1+2=3 ...
Es sollten n! Kombinationen sein.

Die Frage lautet:
Wie kann ich mit PHP alle diese Kombinationen auf ihre Gültigkeit überprüfen?
Jedes gegebene Zeichen des Alphabets packe ich in eine Variable und permutiere diese in diversen Schleifen. Mein Gedanke: eval() über die Kombis drüberlaufen lassen und abfragen, wann die Auswertung true ergibt. Ich scheitere aber an der Umsetzung:
$a = 1; $b = "+"; $c = 2; $d = "=="; $e = 3;
if (eval ("$a$b$c$d$e;") == true)

funktioniert nicht, da habe ich wohl eval() noch nicht richtig verstanden.
Kann mir einer auf die Sprünge helfen?

Danke im Voraus.
Gruß, Volker

  1. Ich habe das mal mit regulären Ausdrücken versucht. Ich habe nur das Muster (Zahl Operator Zahl) nicht hinbekommen.

    Du könntest den Ausdruck auch an google schicken und schauen ob die das ausrechnen können. ;-)

    $url = 'http://www.google.de/search?hl=de&q=' . urlencode($ausdruck) . '&meta=';
    $data = file_get_contents($url);
    if (stristr($data,'calc_img.gif')) { ...

  2. Asalam alaykum!

    ich habe folgendes Problem: Ich habe einen Satz von Zahlen und mathematischen Verknüpfungen (in diesem Fall + , * und =) und deren jeweilige Anzahl.
    Alle möglichen Anordnungen dieses Alphabets will ich nun per Brutforce auswerten, ob diese Sinn machen, z.B.:
    123+= ... 1=+32 ... 1+2=3 ...
    Es sollten n! Kombinationen sein.

    In welchem Kontext sollen sie denn Sinn machen? Beispielsweise ist 1+2=3 ein mathematisch korrekter Ausdruck (der sogar wahr ist), in jeder mir bekannten Programmiersprache aber sinnlos (Syntaxfehler).

    Die Frage lautet:
    Wie kann ich mit PHP alle diese Kombinationen auf ihre Gültigkeit überprüfen?

    Was heißt Gültigkeit? Daß die Syntax stimmt, oder daß die Syntax stimmt und die Aussage wahr ist? Beispielsweise ist 1=+32 ein mathematisch korrekter Ausdruck, bloß stimmen tut's halt nicht.

    Jedes gegebene Zeichen des Alphabets packe ich in eine Variable und permutiere diese in diversen Schleifen. Mein Gedanke: eval() über die Kombis drüberlaufen lassen und abfragen, wann die Auswertung true ergibt. Ich scheitere aber an der Umsetzung:
    $a = 1; $b = "+"; $c = 2; $d = "=="; $e = 3;
    if (eval ("$a$b$c$d$e;") == true)

    Wenn Du das Dollarzeichen mit einem Backslash maskierst, wird nicht die Variable eingesetzt, sondern die Zeichenfolge (z.B. $a) für bare Münze genommen. Davon abgesehen: Bist Du sicher, daß immer true rauskommt, wenn der Ausdruck gültig ist? Denke daran, daß beim Rechnen auch mal 0 rauskommen oder ein Vergleich falsch ergeben kann.
    Je nachdem, was Du unter gültig verstehst, ist es vermutlich einfacher, einen eigenen Parser zu schreiben, der den Ausdruck Zeichen für Zeichen durchgeht. Dazu mußt Du Dir allerdings erst einmal die passende Grammatik ausdenken.

    Viele Grüße vom Længlich

    1. Hallo

      In welchem Kontext sollen sie denn Sinn machen? Beispielsweise ist 1+2=3 ein mathematisch korrekter Ausdruck (der sogar wahr ist), in jeder mir bekannten Programmiersprache aber sinnlos (Syntaxfehler).

      in BASIC ist meines Wissens das Gleichheitszeichen nicht nur Zuweisungs- sondern auch Vergleichsoperator:

        
      Sub test()  
          If 1 + 2 = 3 Then  
              MsgBox "Toll!"  
          Else  
              MsgBox "Schade!"  
          End If  
      End Sub  
      
      

      gibt (Excel-VBA) Toll! aus.

      Freundliche Grüße

      Vinzenz

      1. Vanakkam!

        in BASIC ist meines Wissens das Gleichheitszeichen nicht nur Zuweisungs- sondern auch Vergleichsoperator:

        Stimmt, daran habe ich nicht mehr gedacht. Basic ist bei mir schon etwas länger her. ;-)
        Danke für die Korrektur!

        Oh, äh, in Pascal/Delphi war doch = zum Vergleichen und := die Zuweisung, oder? Und in ABAP und PL/SQL müßte der Vergleich auch mit = gehen. Hmm... ich ziehe die Aussage lieber komplett zurück. Scheinen ja doch einige Sprachen zu sein. ;-)

        Viele Grüße vom Længlich

    2. Wenn Du das Dollarzeichen mit einem Backslash maskierst, wird nicht die Variable eingesetzt, sondern die Zeichenfolge (z.B. $a) für bare Münze genommen. Davon abgesehen: Bist Du sicher, daß immer true rauskommt, wenn der Ausdruck gültig ist? Denke daran, daß beim Rechnen auch mal 0 rauskommen oder ein Vergleich falsch ergeben kann.

      Hm, anscheinend liegt der Fehler in meinem if-Konstrukt und ich verlange da Unmögliches. Ein
      var_dump (eval("$a$b$c$d$e;"));
      liefert mir NULL.
      Also geht das so wie ich dachte gar nicht.

      Je nachdem, was Du unter gültig verstehst, ist es vermutlich einfacher, einen eigenen Parser zu schreiben, der den Ausdruck Zeichen für Zeichen durchgeht. Dazu mußt Du Dir allerdings erst einmal die passende Grammatik ausdenken.

      Eben. Es gibt doch bestimmt eine "konventionelle" Möglichkeit, mein Vorhaben unter PHP zu realisieren.
      Nur wie? Meine Idee mit eval() ist gescheitert, hat jemand einen Tipp?

      Gruß, Volker

      1. Shalom!

        Hm, anscheinend liegt der Fehler in meinem if-Konstrukt und ich verlange da Unmögliches. Ein
        var_dump (eval("$a$b$c$d$e;"));
        liefert mir NULL.
        Also geht das so wie ich dachte gar nicht.

        Wenn ich es richtig verstehe, liefert eval() das Ergebnis nur zurück, wenn es ausdrücklich dazu aufgefordert wird:
        "As of PHP 4, eval() returns NULL unless return is called in the evaluated code, in which case the value passed to return is returned. If there is a parse error in the evaluated code, eval() returns FALSE and execution of the following code continues normally. It is not possible to catch a parse error in eval()  using set_error_handler()."
        (http://de.php.net/eval)
        Vielleicht klappt es mit var_dump(eval("return $a$b$c$d$e;")); (ungetestet)?

        Eben. Es gibt doch bestimmt eine "konventionelle" Möglichkeit, mein Vorhaben unter PHP zu realisieren.
        Nur wie? Meine Idee mit eval() ist gescheitert, hat jemand einen Tipp?

        Die Frage ist, wie konventionell Dein Vorhaben ist. ;-)
        Aber Deine Grammatik ist doch eigentlich sehr einfach, oder? Nach dem, was Du bisher geschrieben hast, berücksichtigst Du ja nicht einmal Klammern. Dann reicht eventuell sogar ein regulärer Ausdruck.
        Stelle erst einmal genau klar, welche Ausdrücke gültig sind:

        • Zahlen mit und ohne Vorzeichen
        • Zahl Operator Zahl
        • Zahl Vergleichsoperator Zahl Operator Zahl
        • Zahl Operator Zahl Vergleichsoperator Zahl
        • ... ?
          Wenn Du so eine Liste hast, findet sich bestimmt recht schnell eine gute Möglichkeit, die Dinger zu erkennen.

        Viele Grüße vom Længlich

        1. Wenn ich es richtig verstehe, liefert eval() das Ergebnis nur zurück, wenn es ausdrücklich dazu aufgefordert wird:
          "As of PHP 4, eval() returns NULL unless return is called in the evaluated code, in which case the value passed to return is returned. If there is a parse error in the evaluated code, eval() returns FALSE and execution of the following code continues normally. It is not possible to catch a parse error in eval()  using set_error_handler()."
          (http://de.php.net/eval)
          Vielleicht klappt es mit var_dump(eval("return $a$b$c$d$e;")); (ungetestet)?

          Ha, sieh einer an, return ist die Lösung.
          Da wäre ich nicht drauf gekommen, danke.

          Gruß, Volker

  3. PS: Was heißt eigentlich funktioniert nicht? Schau mal was eval()  macht und welchen Rückgabewert die Funktion hat.

    Das hier geht:
    $a = 1; $b = "+"; $c = 2; $e = 3;
    eval('$x = '.$a.$b.$c.';');
    if ($x == $e) {
    echo 'wahr';
    } else{
    echo 'falsch';
    }