questa è una classe che ho scritto tempo fa per analizzare espressioni aritmetiche con i quattro operatori +-*/ e una serie di costanti (cioè stringhe a cui è associato un valore) predefinite.
Sicuramente un esperto nel campo sorriderebbe a tutte le ingenuità che ho scritto, ma per quello che mi serviva ha sempre funzionato
Forse ti può essere utile...
codice:
/*
* Copyright (C) 2003 Lorenzo Blanco
*
* Require JDK 1.3
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Send questions or suggestions to webmaster@lorenzoblanco.it
*
*/
import java.util.*;
/**
* La classe AnalizzatoreEspressioni permette di calcolare delle
* espressioni aritmetiche.
*
* @version 1.0
* @author Lorenzo Blanco
*/
public class AnalizzatoreEspressioni {
public static double risultEspressione(String espressione) throws EsprException {
return risultEspressione(espressione,null);
}
public static double risultEspressione(String espressione, HashMap mappaCostanti) throws EsprException {
// if (mappaCostanti != null) {
//
// // stampa gli indirizzi IVN con gli indirizzi delle routine di servizio
// Set set = mappaCostanti.entrySet();
//
// Iterator i = set.iterator();
//
// while (i.hasNext()) {
// Map.Entry la = (Map.Entry) i.next();
// System.out.println(la.getKey() + ": " + la.getValue());
// }
// }
if (!veificaParentesi(espressione)) {
throw new EsprException("Errore nelle parentesi");
}
// ad ogni coppia parentesi aperta/chiusa sostituisce il valore
String daAnalizzare = espressione;
int indiceAperta = daAnalizzare.indexOf('(');
int indiceChiusa = daAnalizzare.indexOf(')');
int indiceUCPDUA = ultimaChiusaPrimaDiUnaAperta(daAnalizzare);
while (indiceAperta != -1) {
daAnalizzare = daAnalizzare.substring(0,indiceUCPDUA) +
String.valueOf(risultEspressioneSenzaPar(
daAnalizzare.substring(indiceUCPDUA+1,indiceChiusa),
mappaCostanti)) +
daAnalizzare.substring(indiceChiusa+1);
indiceAperta = daAnalizzare.indexOf('(');
indiceChiusa = daAnalizzare.indexOf(')');
indiceUCPDUA = ultimaChiusaPrimaDiUnaAperta(daAnalizzare);
// System.out.println(daAnalizzare);
}
return risultEspressioneSenzaPar(daAnalizzare, mappaCostanti);
}
private static int ultimaChiusaPrimaDiUnaAperta(String dove) {
int indiceCercato = -1;
boolean trovata = false;
boolean trovataTemp;
for (int i = 0; !trovata && i < dove.length(); i++) {
// se trova una '(' verifica che prima della prossima ')' non ci siano '('
if (dove.charAt(i) == '(') {
trovataTemp = true;
for (int j = i+1; trovataTemp && j < dove.indexOf(')'); j++) {
if (dove.charAt(j) == '(') {
trovataTemp = false;
}
}
if (trovataTemp) {
indiceCercato = i;
trovata = true;
}
}
}
return indiceCercato;
}
// metodo che verifica che ci siano un numero uguale di parentesi chiuse e aperte
private static boolean veificaParentesi(String dove) {
int daChiudere = 0;;
for (int i = 0; i < dove.length(); i++) {
if (dove.charAt(i) == '(') {
daChiudere++;
} else if (dove.charAt(i) == ')') {
daChiudere--;
}
if (daChiudere < 0) {
return false;
}
}
if (daChiudere == 0) {
return true;
} else {
return false;
}
}
private static double risultEspressioneSenzaPar(String espressione, HashMap mappaCostanti) throws EsprException {
// System.out.println("\t"+espressione);
if (espressione.length() < 1) {
throw new EsprException("L'espressione è vuota");
}
// uso del '-' come cambio di segno
if (espressione.startsWith("-")) {
espressione = "0"+espressione;
}
int primoOperando, secondoOperando;
int indicePrimoPiuOMeno = trovaPrimoPiuOMeno(espressione);
int indicePrimoDiviso = trovaPrimoDiviso(espressione);
int indicePrimoPer = trovaPrimoPer(espressione);
// se non ci sono '+' o '-'
if (indicePrimoPiuOMeno == -1) {
// se non ci sono '*'
if (indicePrimoPer == -1) {
// se non ci sono '/'
if (indicePrimoDiviso == -1) {
// è un numero puro, quindi lo restituisce
try {
// se non è disponibile la mappa delle costanti
if (mappaCostanti == null) {
return new Double(espressione).doubleValue();
} else {
if (mappaCostanti.containsKey(espressione)) {
Comando c = (Comando) mappaCostanti.get(espressione);
// se è una EQU
if (c.direttiva == 4) {
return (double) ((Long) c.argDirett.get(1)).longValue();
// altrimenti è una D*
} else {
return (double) ((Long) c.argDirett.get(2)).longValue();
}
} else {
return new Double(espressione).doubleValue();
}
}
} catch (NumberFormatException nfe) {
throw new EsprException("La costante "+espressione+" non è valida");
}
// ci sono '/'
} else {
return risultEspressioneSenzaPar(espressione.substring(0,indicePrimoDiviso), mappaCostanti) /
risultEspressioneSenzaPar(espressione.substring(indicePrimoDiviso+1), mappaCostanti);
}
// ci sono '*'
} else {
return risultEspressioneSenzaPar(espressione.substring(0,indicePrimoPer), mappaCostanti) *
risultEspressioneSenzaPar(espressione.substring(indicePrimoPer+1), mappaCostanti);
}
// c'è almeno un '+' o un '-'
} else {
double risultato = risultEspressioneSenzaPar(
espressione.substring(0,trovaPrimoPiuOMeno(espressione)),
mappaCostanti);
String ancoraDaAnalizzare = espressione;
int indPrimoPiuOMeno,indSecondoPiuOMeno;
while (trovaPrimoPiuOMeno(ancoraDaAnalizzare) != -1) {
indPrimoPiuOMeno = trovaPrimoPiuOMeno(ancoraDaAnalizzare);
indSecondoPiuOMeno = trovaSecondoPiuOMeno(ancoraDaAnalizzare);
//System.out.println(ancoraDaAnalizzare + " | " + indicePiuOMeno);
if (ancoraDaAnalizzare.charAt(indPrimoPiuOMeno) == '+') {
risultato += risultEspressioneSenzaPar(
ancoraDaAnalizzare.substring(indPrimoPiuOMeno+1,indSecondoPiuOMeno),
mappaCostanti);
} else if (ancoraDaAnalizzare.charAt(indPrimoPiuOMeno) == '-') {
risultato -= risultEspressioneSenzaPar(
ancoraDaAnalizzare.substring(indPrimoPiuOMeno+1,indSecondoPiuOMeno),
mappaCostanti);
} else {
System.out.println("Questo non dovrebbe essere visualizzato (1)");
}
ancoraDaAnalizzare = ancoraDaAnalizzare.substring(indPrimoPiuOMeno+1);
// System.out.println("\t\tris.int.: "+risultato);
}
return risultato;
}
}
private static int trovaPrimoPiuOMeno(String dove) {
for (int i = 0; i < dove.length(); i++) {
if (dove.charAt(i) == '+' || dove.charAt(i) == '-') {
return i;
}
}
return -1;
}
private static int trovaSecondoPiuOMeno(String dove) {
boolean trovatoPrimo = false;
for (int i = 0; i < dove.length(); i++) {
if (dove.charAt(i) == '+' || dove.charAt(i) == '-') {
if (!trovatoPrimo) {
trovatoPrimo = true;
} else {
return i;
}
}
}
return dove.length();
}
private static int trovaPrimoDiviso(String dove) {
for (int i = 0; i < dove.length(); i++) {
if (dove.charAt(i) == '/') {
return i;
}
}
return -1;
}
private static int trovaPrimoPer(String dove) {
for (int i = 0; i < dove.length(); i++) {
if (dove.charAt(i) == '*') {
return i;
}
}
return -1;
}
public static void main(String[] args) {
String test = "60/3*2+3+66/2*2";
test = "(2+30*2/3)*3+((3+2)*3+300/(90+2*7))/2";
// righe di codice del JPD132 al 28/4/2003
test = "294+151+51+349+63+2965+391+203+69+138+35+1087+900+151+2604+42+316";
try {
System.out.println(risultEspressione(test));
} catch (EsprException ee) {
System.out.println(ee);
}
// System.out.println(veificaParentesi("( () () ( () () ) )"));
// System.out.println(ultimaChiusaPrimaDiUnaAperta("( () () ( () () ) )"));
}
}