2011-01-24 28 views
5

Ecco uno interessante. Qualcuno ha una buona RegEx per convertire tutto (prima)^(seconda) in Math.pow ((prima), (seconda))?RegEx per a^b invece di pow (a, b)

EDIT:

il migliore che ho finora è

s = s.replace(/((?:\d+\.?\d*)|\w+|\((?:(?:[^\(\)]*(?:\([^\(\)]*\)))*)\))\s*\^\s*((?:\d+\.?\d*)|\w+|\((?:(?:[^\(\)]*(?:\([^\(\)]*\)))*)\))/g, 'Math.pow($1, $2)') // replace expression^expression with Math.pow($1, $2) 

Le risposte finora non sono sufficienti generale. Non coprono qualcosa come (var1 + var2)^2 figuriamoci (var1 * (var2 + var3))^2

La soluzione dovrà funzionare con parentesi.

È possibile utilizzare strfriend.com per visualizzare la regex durante la creazione. Questo è quello che ho fatto.

+3

E il più vicino che hai adesso è ...? – Oswald

+4

Come convertire "a * b^c'? 'a^b + c'? 'a^b^c'? –

+5

Non può essere eseguito con la normale espressione regolare. Richiede la ricorsione arbitraria. Se vuoi una risposta ti suggerisco di aumentare la taglia, questo è un problema abbastanza complicato. – kelloti

risposta

11

Questo non può essere fatto con espressioni regolari (almeno non senza un sacco di fatica). Devi considerare diversi livelli di parentesi, che non possono essere gestiti con una semplice espressione regolare. Suggerisco di cercare una libreria in grado di analizzare l'espressione matematica. O dovrai limitare l'espressione possibile a qualcosa che puoi gestire con una semplice espressione regolare.

V'è la possibilità di definire il nome e il bilanciamento gruppi di cattura in un'espressione regolare che possono essere utilizzati (backreferenced) nella stessa espressione regolare. Con questo dovresti definire il sottoinsieme desiderato della sintassi matematica e entrambe le acquisizioni per i parametri. Suggerisco di non reinventare la ruota e utilizzare una libreria JS.

http://snippets.dzone.com/posts/show/2207

+3

Mattias è proprio qui; se hai una lingua con costrutti nidificati come Parens, allora una lingua normale non la taglierà, anzi, è lì nella definizione di 'linguaggio normale'. Meglio iniziare a scrivere un parser o trovare uno dei tanti là fuori. –

2

Si potrebbe utilizzare String.replace:

> s = "hello 2^3 pow!" 
> s.replace(/(\d+)\^(\d+)/, "Math.pow($1, $2)") 
"hello Math.pow(2, 3) pow!" 
1

Supponendo che si desidera convertire i file di origine o qualcosa di simile, prendere uno script Perl in esecuzione su file di origine e utilizzare Math::Expression::Evaluator::Parser. Dalla sinossi:

use Math::Expression::Evaluator::Parser; 

my $exp = '2 + a * 4'; 
my $ast = Math::Expression::Evaluator::Parser::parse($exp, {}); 
# $ast is now something like this: 
# $ast = ['+', 
#   2, 
#   ['*', 
#   ['$', 'a'], 
#   4 
#   ] 
#  ]; 

sembra che in grado di gestire exponentiations facilmente. Così l'AST nel tuo caso sarebbe qualcosa di simile:

# $ast = ['^', 
#   base, 
#   exp 
#  ]; 

si potrebbe costruire l'espressione desiderata 'Math.pow (base, exp)' da (ricorsivamente) ricomporre una stringa dalla 'base' e 'exp' sottostrutture.

Se si desidera implementare una calcolatrice in JavaScript, è necessario ovviamente un JavaScript-Parser oppure si può fare affidamento su un back-end del server implementato utilizzando Math :: Expression :: Evaluator.

+0

Questo, o una risposta che discute dell'implementazione di funzionalità simili in JS è la risposta corretta. – Incognito

1

La cattiva notizia: le espressioni regolari non è tagliato (come molte risposte indicano), sarà necessario scrivere un parser per questo.

La buona notizia: è possibile in modo relativamente facile farlo da soli in quasi tutte le lingue, scrivendo un parser discesa ricorsiva. Dovresti ovviamente riutilizzare il più possibile il codice esistente, ma codificare un parser di discendenza ricorsiva (e vedere come codi regole di precedenza) può essere raccomandato esclusivamente per l'esperienza illuminante.

raccogliere qualsiasi libro sulla costruzione del compilatore e leggere i primi capitoli di analisi. Vorrei suggerire this freely available book di Niklaus Wirth, cercare 4.1 "Il metodo della discesa ricorsiva".

0

Dai un'occhiata a Jison, un generatore di parser Javascript.

In particolare, controllare il loro calculator demo

0
var caretReplace = function(_s) { 
    if (_s.indexOf("^") > -1) { 
     var tab = []; 
     var powfunc="Math.pow"; 
     var joker = "___joker___"; 
     while (_s.indexOf("(") > -1) { 
      _s = _s.replace(/(\([^\(\)]*\))/g, function(m, t) { 
       tab.push(t); 
       return (joker + (tab.length - 1)); 
      }); 
     } 

     tab.push(_s); 
     _s = joker + (tab.length - 1); 
     while (_s.indexOf(joker) > -1) { 
      _s = _s.replace(new RegExp(joker + "(\\d+)", "g"), function(m, d) { 
       return tab[d].replace(/(\w*)\^(\w*)/g, powfunc+"($1,$2)"); 
      }); 
     } 
    } 
    return _s; 
}; 
  1. console.log(caretReplace("(3*(f(x^2)-2)^2+1^5-g(2^3+1)^5)^(9-2^3)"));Math.pow((3*Math.pow((f(Math.pow(x,2))-2),2)+Math.pow(1,5)-Math.pow(g(Math.pow(2,3)+1),5)),(9-Math.pow(2,3))).

  2. L'espressione matematica deve essere valida, con parentesi aperte e chiuse ben bilanciate.

  3. È possibile sostituire Math.pow con qualsiasi nome di funzione desiderato.

  4. Ho fatto questo, sostituendo tutte le parentesi, dal più interno al più esterno, con testi non matematica (___joker___0, ___joker___1, eccetera). Alla fine analizzo tutte queste stringhe gerarchicamente, per sostituire i caret sulle espressioni non parentesi.

Problemi correlati