125 votes

Évaluation d'une chaîne de caractères en tant qu'expression mathématique en JavaScript

Comment analyser et évaluer une expression mathématique dans une chaîne de caractères (par ex. '1+1' ) sans invoquer eval(string) pour obtenir sa valeur numérique ?

Avec cet exemple, je veux que la fonction accepte '1+1' et retourner 2 .

99voto

Rafael Vega Points 2250

Vous pouvez utiliser le Bibliothèque JavaScript Expression Evaluator qui vous permet de faire des choses comme :

Parser.evaluate("2 ^ x", { x: 3 });

Ou mathjs qui permet des choses comme :

math.eval('sin(45 deg) ^ 2');

J'ai fini par choisir mathjs pour l'un de mes projets.

27voto

kennebec Points 71

Vous pouvez faire + ou - facilement :

function addbits(s) {
  var total = 0,
      s = s.match(/[+\-]*(\.\d+|\d+(\.\d+)?)/g) || [];

  while (s.length) {
    total += parseFloat(s.shift());
  }
  return total;
}

var string = '1+23+4+5-30';
console.log(
  addbits(string)
)

Des mathématiques plus compliquées rendent l'évaluation plus attrayante - et certainement plus simple à écrire.

27voto

Aniket Kudale Points 250

Simple et élégant avec Function()

function parse(str) {
  return Function(`'use strict'; return (${str})`)()
}

parse("1+2+3");

19voto

bdukes Points 54833

Quelqu'un doit analyser cette chaîne. Si ce n'est pas l'interpréteur (par l'intermédiaire de eval ), vous devrez écrire une routine d'analyse pour extraire les nombres, les opérateurs et tout ce que vous voulez prendre en charge dans une expression mathématique.

Donc, non, il n'y a pas de moyen (simple) sans eval . Si vous êtes préoccupé par la sécurité (parce que l'entrée que vous analysez ne provient pas d'une source que vous contrôlez), vous pouvez peut-être vérifier le format de l'entrée (via un filtre regex de liste blanche) avant de la transmettre à eval ?

16voto

Stefan Gabos Points 94

Une alternative à l'excellente réponse de @kennebec, en utilisant une expression régulière plus courte et en autorisant les espaces entre les opérateurs.

function addbits(s) {
    var total = 0;
    s = s.replace(/\s/g, '').match(/[+\-]?([0-9\.\s]+)/g) || [];
    while(s.length) total += parseFloat(s.shift());
    return total;
}

Utilisez-le comme

addbits('5 + 30 - 25.1 + 11');

Mise à jour

Voici une version plus optimisée

function addbits(s) {
    return (s.replace(/\s/g, '').match(/[+\-]?([0-9\.]+)/g) || [])
        .reduce(function(sum, value) {
            return parseFloat(sum) + parseFloat(value);
        });
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X