eval string Minuszeichen

Jofre

Erfahrenes Mitglied
Guten Morgen,

ich habe einen "Rechen" String

z.B.

erg= "3 + 4 *5 - 6 +2 "

den kann ich berechnen mit
erg=eval(erg)

Bei der Berechnung gilt die Regel Punktrechnung vor Strichrechnung.
Ich möchte den String aber ohne diese Rechenvorschrift berechnen

Mein Ansatz war:

var erg=eval((string.slice(0,3)));
erg= eval(erg +string.slice(3,5));
erg=eval(erg +string.slice(5,7));

Das klappt nicht wenn ein Minus auftaucht.

Lösungsidee?
 
Ich möchte den String aber ohne diese Rechenvorschrift berechnen
Wie genau meinst du das?
Meinst du quasi von vorne nach hinten:
Code:
  3 + 4 * 5 - 6 + 2
= 7     * 5 - 6 + 2
= 35        - 6 + 2
= 29            + 2
= 31

Ich verstehe zwar den Sinn davon nicht, aber okay :D
Ich würde dafür so vorgehen:


1) Finde den Index des zweiten Operators:

Code:
  3 + 4 * 5 - 6 + 2
        ^
        | den Index dieses Zeichens


2) Evaluiere den Teilstring bis zu diesem Index:

Code:
ergebnis = eval("3 + 4 "); // = 7


3) Baue einen neuen String aus dem Ergebnis von 2) und dem hinteren Teil deiner Eingabe:

Code:
neuer_string = ergebnis + "* 5 - 6 + 2";
               \  =7  /   \   Teil 2   /

4) Wiederhole 1). Wenn es nur noch einen Operator gibt, ruf ein letztes Mal eval() auf:

Code:
  7*5 - 6 + 2
      ^
      | hier wird als nächstes gesplittet

  35- 6 + 2
        ^
        | danach hier

  29+ 2 // nur noch ein Operator -> ruf ein letztes Mal eval() auf

  eval("29+ 2"); // = 31


Kann natürlich auch sein, dass ich das ganze irgendwie falsch verstanden habe...

Gruß Technipion
 
vielleicht reicht es Klammern zu setzen?
Javascript:
eval("(3 + 4) * 5 - 6 + 2 ")

Funktioniert bei mir auch so ohne die Kommas oben( Name dafür entfallen )
Code:
 eval((3 + 4) * 5 - 6 + 2)

Aber wahrscheinlich ist der weg zu einfach.
Bei Php sagt man doch immer das eval böse ist . Ist das bei Javascript nicht das gleiche ?
Las doch eval weg, weil zb beim Alert wird die richtige Lösung ( 31 ) auch so angezeigt
Code:
 alert((3 + 4) * 5 - 6 + 2)
Also müsste das doch auch ohne eval gehen oder sehe ich das jetzt falsch ???
 
Bei Php sagt man doch immer das eval böse ist . Ist das bei Javascript nicht das gleiche ?
Jein. Grundsätzlich stimmt es natürlich, dass man auf eval() (in egal welcher Sprache) verzichten sollte, falls das geht. Der Grund warum in PHP, aber auch in Python, Java, und den meisten anderen interpretierten Sprachen davon abgeraten wird ist, dass es prinzipiell einem Angreifer ermöglicht seinen Code in ein sonst (hoffentlich) gesichertes Computersystem einzuschleusen.

Wenn du z.B. in PHP sowas hier bringst eval($_POST["rechnung"]); kann ein Angreifer ja relativ schnell eigenen Code per POST an deinen Server senden, und seinen eigenen Code auf deinem System ausführen. Das ist schlecht.

Bei JavaScript könnte dir das im Prinzip auch passieren, aber ich gehe mal davon aus, dass @Jofre hier ein Programm für den Client entwirft, also Code der vom Server gedownloaded und dann im Browser ausgeführt wird. Da entfällt das Risiko im Pinzip, denn falls etwas schief geht ist es auf dem Rechner des Clients.

Man muss natürlich beachten wie genau das Resultat von eval(); hier gehandhabt wird. Es wäre z.B. eine sehr schlechte Idee den Ausdruck in JavaScript mit eval(); auszuwerten und dann in irgendeiner Form bei einem Datenbankzugriff zu verwenden...
Es gilt: Don't trust the user!

Fun Fact: Eigentlich bietet JavaScript richtig nette Spielereien mit eval(); (guckst du z.B. hier math.js | an extensive math library for JavaScript and Node.js), aber da Jofre gegen die gottgegebene Operator-Rangfolge verstoßen will, muss er sich da selbst etwas einfallen lassen.

Fun Fact 2: Mal von den Sicherheitslücken abgesehen kann bei eval();-Befehlen noch viel mehr schief gehen. Man stelle sich vor, was wohl bei einem kleinen Tippfehler mit eval("9722349**662584155"); passiert... (Tipp: Die Zahl braucht mehr als 15 GB RAM ;))

Gruß Technipion
 
Hi,

oder als Einzeiler-Spielerei mit regulären Ausdrücken und Array-Funktion:
Javascript:
"3 + 4 *5 - 6 +2 ".match(/(\d+)|([\+\*\-\/\:])/g).reduce((accu, curr) => isNaN(curr) ? (accu + (curr === ':' ? '/' : curr)) : eval(accu + curr));

Ciao
Quaese
 
Bei JavaScript könnte dir das im Prinzip auch passieren, aber ich gehe mal davon aus, dass @Jofre hier ein Programm für den Client entwirft, also Code der vom Server gedownloaded und dann im Browser ausgeführt wird. Da entfällt das Risiko im Pinzip, denn falls etwas schief geht ist es auf dem Rechner des Clients.
Das stimmt so nicht ganz. Zum Beispiel können Nutzerdaten und die aktuelle Session gestohlen werden. Das ist im Prinzip dasselbe Problem wie bei XSS.

Fun Fact: Eigentlich bietet JavaScript richtig nette Spielereien mit eval(); (guckst du z.B. hier math.js | an extensive math library for JavaScript and Node.js), aber da Jofre gegen die gottgegebene Operator-Rangfolge verstoßen will, muss er sich da selbst etwas einfallen lassen.
Die verlinkte Bibliothek hat eigentlich nichts mit dem JS eval zu tun, außer dass sie ihre "parse & evaluate" Funktion auch eval genannt hat. Deren Funktion parst den mathematischen Ausdruck aber wirklich als solchen und nicht als JS.
Möglicherweise könnte man aber math.js so erweitern, indem man neue Operatoren definiert, die andere Precedence-Regeln haben.

Fun Fact 2: Mal von den Sicherheitslücken abgesehen kann bei eval();-Befehlen noch viel mehr schief gehen. Man stelle sich vor, was wohl bei einem kleinen Tippfehler mit eval("9722349**662584155"); passiert... (Tipp: Die Zahl braucht mehr als 15 GB RAM ;))
Nachdem JS keine built-in BigNum Library benutzt, sondern 64-Bit Double Zahlen, ist das Ergebnis hier dank Overflow +Infinity und verbraucht nicht mehr CPU-Zyklen oder Speicher als eine Double-Multiplikation normalerweise im Worst Case verbraucht ;)
 
Nachdem JS keine built-in BigNum Library benutzt, sondern 64-Bit Double Zahlen, ist das Ergebnis hier dank Overflow +Infinity und verbraucht nicht mehr CPU-Zyklen oder Speicher als eine Double-Multiplikation normalerweise im Worst Case verbraucht ;)
Hast mich erwischt, ich war aus irgendeinem Grund gerade bei Python :LOL:

Die verlinkte Bibliothek hat eigentlich nichts mit dem JS eval zu tun, außer dass sie ihre "parse & evaluate" Funktion auch eval genannt hat.
Den Link hatte ich nur gepostet, weil sich Jofres Frage sehr nach einem starken Bezug zur Mathematik angehört hat. War also nur ins Blaue geraten.

@Jofre: @ComFreek hat da völlig Recht, du machst dich mit eval() für XSS (Cross-Site-Scripting) und ähnliche Attacken verwundbar. Im Grunde wäre es das beste, komplett auf eval() zu verzichten.
Am besten schreibst du uns mal, was genau du vor hast, dann basteln wir etwas zusammen.

Gruß Technipion
 
Hast mich erwischt, ich war aus irgendeinem Grund gerade bei Python :LOL:


Den Link hatte ich nur gepostet, weil sich Jofres Frage sehr nach einem starken Bezug zur Mathematik angehört hat. War also nur ins Blaue geraten.

@Jofre: @ComFreek hat da völlig Recht, du machst dich mit eval() für XSS (Cross-Site-Scripting) und ähnliche Attacken verwundbar. Im Grunde wäre es das beste, komplett auf eval() zu verzichten.
Am besten schreibst du uns mal, was genau du vor hast, dann basteln wir etwas zusammen.

Gruß Technipion
 
Zum Hintergrund

Ich möchte Kettenrechnzungen durchführen. Dafür erzeuge ich strings wie im obigen Beispiel. Die strings nuzen + - * / .

Wenn ich eine Ketten rechnung durchführe dann rechne ich stur von links nach rechts.
Der Ansatz von Quaese funktioniert. ich möchte aber nicht gerne etwas nutzen, das ich nicht verstehe.

Wahrscheinlich bleibt mir nur der Ansatz(Basti= mit dem Klammern.
Das wird aber eine grosse Fummelei . Der String könnte auch sein:

3-5*7 *2 + 4*-5 +2

Vielleicht ist es der einfachste und transparenste Weg jede Rechenoperation zu klammern.

(((((3-5)*2)+4)-5)+2)
 
Zurück