Interpretador de expressÕes aritmÉticas bÁsicas

0 respostas
F

De vez enquanto existe a necessidade de tratar expressões aritméticas básicas (adição, subtração, multiplicação e divisão) que retornem o resultado em valores reais considerando a prioridade das operações a serem efetuadas.

O código abaixo permitir passar como parâmetro uma String com a expressão aritmética a ser interpretada e retornar um valor do tipo Double.

A prioridade das operações é: parênteses "()", divisão "/", multiplicação "*", adição "+" e subtração "-".

Podem ser utilizados os símbolos {} e [] para separar as expressões.

O nome da classe é: Expressao.

O método público é: calcularExpressao.

Exemplo de uso:

Expressao expressao = new Expressao();
Double resultado = expressao.calcularExpressao("((10/5)+10*2+(20/2))");

Abaixo segue o código do interpretador. Pode ser alterado para permitir outras operações.

import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;

/**
 *
 * @author Francisco Januario
 * @date 14/09/2011 
 * @modified 13/01/2012
 * @version 1.1
 *
 */
public class Expressao {
    
    private int id;
    private int nivel;    
    private int posicao1;
    private int posicao2;
    private String expressao;
    private Double resultado;
    
    // O simbolo "M" (pode ser outro) para a constante operadorMenos
    // é utilizado para substituir o operador "-" durante o cálculo
    // com número negativos.
    private static String operadorMenos = "M"; 
    
    public Expressao(){        
    }
    
    private boolean isNumero(String numero){
        boolean bNumero = true;
        
        if(!numero.equals("0")&&!numero.equals("1")&&
           !numero.equals("2")&&!numero.equals("3")&&
           !numero.equals("4")&&!numero.equals("5")&&
           !numero.equals("6")&&!numero.equals("7")&&
           !numero.equals("8")&&!numero.equals("9")&&
           !numero.equals(".")&&!numero.equals(",")&&
           !numero.equals(operadorMenos)){
           bNumero = false;
        }
        
        return bNumero;
    }
    
    private Double calcular(String expressao){
        Double resultado = 0.0;
        String sExpressao = expressao;
        
        if(sExpressao.charAt(0)=='-')
            sExpressao = operadorMenos + sExpressao.substring(1);
        
        Double res = 0.0;
        boolean oper;
        while(sExpressao.contains("/")||
              sExpressao.contains("*")||
              sExpressao.contains("+")||
              sExpressao.contains("-")){
            oper = false;
            Double vl1 = 0.0;
            Double vl2 = 0.0;
            String sl1 = "";
            String sl2 = "";
            int iPos1 = 0;
            int iPos2 = 0;
            
            try{
                // DIVISÃO
                if(!oper&&sExpressao.contains("/")){
                   int i;
                   // Capturando o primeiro numero antes do operador
                   for(i=sExpressao.indexOf("/")-1; i >= 0; i--){
                       if(isNumero(sExpressao.substring(i, i+1)))
                           sl1 = sExpressao.substring(i, i+1) + sl1;
                       else{
                           break;
                       }
                   }
                   iPos1 = i + 1;
                   if(sl1.contains(","))
                       sl1 = sl1.substring(0, sl1.indexOf(",")-1) + "." + sl1.substring(sl1.indexOf(",")+1);
                   if(sl1.contains(operadorMenos))
                       sl1 = sl1.replace(operadorMenos, "-");
                   vl1 = Double.parseDouble(sl1); 
                   // Capturando o primeiro numero antes do operador
                   for(i=sExpressao.indexOf("/")+1; i<sExpressao.length(); i++){
                       if(isNumero(sExpressao.substring(i, i+1)))
                           sl2 = sl2 + sExpressao.substring(i, i+1);
                       else{
                           break;
                       }
                   }
                   iPos2 = i - 1;
                   if(sl2.contains(","))
                       sl2 = sl2.substring(0, sl2.indexOf(",")-1) + "." + sl2.substring(sl2.indexOf(",")+1);
                   vl2 = Double.parseDouble(sl2); 
                   // Calculando o resultado
                   if(vl2 > 0)
                      res = vl1 / vl2;
                   else
                      res = 0.0;
                   sExpressao = sExpressao.substring(0, iPos1) + new Double(res).toString() + 
                                sExpressao.substring(iPos2+1);
                   oper = true;
                }
                // MULTIPLICAÇÃO
                if(!oper&&sExpressao.contains("*")){
                   // Capturando o primeiro numero antes do operador
                   int i;
                   for(i=sExpressao.indexOf("*")-1; i >= 0; i--){
                       if(isNumero(sExpressao.substring(i, i+1)))
                           sl1 = sExpressao.substring(i, i+1) + sl1;
                       else{
                           break;
                       }
                   }
                   iPos1 = i + 1;
                   if(sl1.contains(","))
                      sl1 = sl1.substring(0, sl1.indexOf(",")-1) + "." + sl1.substring(sl1.indexOf(",")+1);
                   if(sl1.contains(operadorMenos))
                       sl1 = sl1.replace(operadorMenos, "-");
                   vl1 = Double.parseDouble(sl1); 
                   // Capturando o primeiro numero antes do operador
                   for(i=sExpressao.indexOf("*")+1; i<sExpressao.length(); i++){
                       if(isNumero(sExpressao.substring(i, i+1)))
                           sl2 = sl2 + sExpressao.substring(i, i+1);
                       else{
                           break;
                       }
                   }
                   iPos2 = i - 1;
                   if(sl2.contains(","))
                      sl2 = sl2.substring(0, sl2.indexOf(",")-1) + "." + sl2.substring(sl2.indexOf(",")+1);
                   vl2 = Double.parseDouble(sl2); 
                   // Calculando o resultado
                   res = vl1 * vl2;
                   sExpressao = sExpressao.substring(0, iPos1) + new Double(res).toString() + 
                                sExpressao.substring(iPos2+1);
                   oper = true;
                }
                // ADIÇÃO
                if(!oper&&sExpressao.contains("+")){
                   // Capturando o primeiro numero antes do operador
                   int i;
                   for(i=sExpressao.indexOf("+")-1; i >= 0; i--){
                       if(isNumero(sExpressao.substring(i, i+1)))
                           sl1 = sExpressao.substring(i, i+1) + sl1;
                       else{
                           break;
                       }
                   }
                   iPos1 = i + 1;
                   if(sl1.contains(","))
                       sl1 = sl1.substring(0, sl1.indexOf(",")-1) + "." + sl1.substring(sl1.indexOf(",")+1);
                   if(sl1.contains(operadorMenos))
                       sl1 = sl1.replace(operadorMenos, "-");
                   vl1 = Double.parseDouble(sl1); 
                   // Capturando o primeiro numero antes do operador
                   for(i=sExpressao.indexOf("+")+1; i<sExpressao.length(); i++){
                       if(isNumero(sExpressao.substring(i, i+1)))
                           sl2 = sl2 + sExpressao.substring(i, i+1);
                       else{
                           break;
                       }
                   }
                   iPos2 = i - 1;
                   if(sl2.contains(","))
                       sl2 = sl2.substring(0, sl2.indexOf(",")-1) + "." + sl2.substring(sl2.indexOf(",")+1);
                   vl2 = Double.parseDouble(sl2); 
                   // Calculando o resultado
                   res = vl1 + vl2;
                   sExpressao = sExpressao.substring(0, iPos1) + new Double(res).toString() + 
                                sExpressao.substring(iPos2+1);
                   oper = true;
                }
                // SUBTRAÇÃO
                if(!oper&&sExpressao.contains("-")){
                   // Capturando o primeiro numero antes do operador
                   int i;
                   for(i=sExpressao.indexOf("-")-1; i >= 0; i--){
                       if(isNumero(sExpressao.substring(i, i+1)))
                           sl1 = sExpressao.substring(i, i+1) + sl1;
                       else{
                           break;
                       }
                   }
                   iPos1 = i + 1;
                   if(sl1.contains(","))
                       sl1 = sl1.substring(0, sl1.indexOf(",")-1) + "." + sl1.substring(sl1.indexOf(",")+1);
                   if(sl1.contains(operadorMenos))
                       sl1 = sl1.replace(operadorMenos, "-");
                   vl1 = Double.parseDouble(sl1); 
                   // Capturando o primeiro numero antes do operador
                   for(i=sExpressao.indexOf("-")+1; i<sExpressao.length(); i++){
                       if(isNumero(sExpressao.substring(i, i+1)))
                           sl2 = sl2 + sExpressao.substring(i, i+1);
                       else{
                           break;
                       }
                   }
                   iPos2 = i - 1;
                   if(sl2.contains(","))
                       sl2 = sl2.substring(0, sl2.indexOf(",")-1) + "." + sl2.substring(sl2.indexOf(",")+1);
                   vl2 = Double.parseDouble(sl2); 
                   // Calculando o resultado
                   res = vl1 - vl2;
                   sExpressao = sExpressao.substring(0, iPos1) + new Double(res).toString() + 
                                sExpressao.substring(iPos2+1);
                   oper = true;
                }
                if(sExpressao.charAt(0)=='-')
                    sExpressao = operadorMenos + sExpressao.substring(1);
            }catch(Exception e){
                JOptionPane.showMessageDialog(null, "Expressão Inválida...");
                return 0.0;
            } 
        }
       
        if(sExpressao.charAt(0)==operadorMenos.charAt(0))
            sExpressao = "-" + sExpressao.substring(1);
                
        resultado = Double.parseDouble(sExpressao);
                
        return resultado;
    }
    
    private String prepararExpressao(String expressao){
        String sExpressao = "";
        if(expressao != null)
           sExpressao = expressao;
        else
           sExpressao = "";
        
        // Tirando todo espaço em branco
        sExpressao = sExpressao.replaceAll(" ", "");
        // Subsituir "[" e "]"
        sExpressao = sExpressao.replace("[", "(");
        sExpressao = sExpressao.replace("]", ")");
        // Subsituir "{" e "}"
        sExpressao = sExpressao.replace("{", "(");
        sExpressao = sExpressao.replace("}", ")");
        
        return "(" + sExpressao + ")";
    }
    
    public Double calcularExpressao(String expressao){
        Double resultado = 0.0;
        String sExpressao = prepararExpressao(expressao);
        
        List<Expressao> expressoes = new ArrayList<Expressao> ();
        
        int nivel = 0;
        int id = 1;
        for(int i=0; i<sExpressao.length(); i++){
            if(sExpressao.charAt(i)=='('){
                nivel++;
                Expressao exp = new Expressao();
                exp.setId(id);
                exp.setNivel(nivel);
                exp.setPosicao1(i);
                expressoes.add(exp);
                id++;
            }
            if(sExpressao.charAt(i)==')'){
               for(int j=0; j<expressoes.size(); j++){
                   Expressao exp = expressoes.get(j);
                   if((exp.getPosicao2()==0)&&exp.getNivel()==nivel){
                      exp.setPosicao2(i);
                      exp.setExpressao(sExpressao.substring(exp.getPosicao1()+1, i));
                      expressoes.set(j, exp);
                   }
               }
               nivel--;
            }
        }   
        nivel = 0;
        for(Expressao exp : expressoes){
            if(exp.getNivel() > nivel)
               nivel = exp.getNivel();
        }
        
        Double res = 0.00;
        int i = nivel;
        while(i >= 1){
            for(int j=0; j<expressoes.size(); j++){
                Expressao exp = expressoes.get(j);
                if(exp.getNivel() == i){
                    if(!exp.getExpressao().contains("(")&&(exp.getResultado()==null)){
                        res = calcular(exp.getExpressao());
                        exp.setResultado(res);
                        expressoes.set(j, exp);
                    }
                }
            }
            i--;
        }

        i = expressoes.size()-1;
        boolean prox;
        String sExpressao2 = "";
        while(i >= 0){
            Expressao exp = expressoes.get(i);
            prox = true;
            if(exp.getResultado()==null){
                for(int j=0; j<expressoes.size(); j++){
                    Expressao exp2 = expressoes.get(j);
                    if(exp.getExpressao().contains("("+exp2.getExpressao()+")")&&
                       (exp2.getResultado()!=null)){
                        sExpressao2 = exp.getExpressao().replace("("+exp2.getExpressao()+")", 
                                                                new Double(exp2.getResultado()).toString());
                        if(!sExpressao2.contains("(")){
                            res = calcular(sExpressao2);
                            exp.setResultado(res);
                            prox = false;
                        }else{
                            exp.setExpressao(sExpressao2);
                        }
                        expressoes.set(i, exp);
                        i = expressoes.size()-1;
                    }
                }
            }
            if(prox)
                i--;
        }

        resultado = expressoes.get(0).getResultado();
        return resultado;
    }

    private Double getResultado() {
        return resultado;
    }

    private void setResultado(Double resultado) {
        this.resultado = resultado;
    }

    private String getExpressao() {
        return expressao;
    }

    private void setExpressao(String expressao) {
        this.expressao = expressao;
    }

    private int getId() {
        return id;
    }

    private void setId(int id) {
        this.id = id;
    }
    
    private int getNivel() {
        return nivel;
    }

    private void setNivel(int nivel) {
        this.nivel = nivel;
    }

    private int getPosicao1() {
        return posicao1;
    }

    private void setPosicao1(int posicao1) {
        this.posicao1 = posicao1;
    }

    private int getPosicao2() {
        return posicao2;
    }

    private void setPosicao2(int posicao2) {
        this.posicao2 = posicao2;
    }
        
}
Criado 14 de setembro de 2011
Respostas 0
Participantes 1