[Resolvido] Validar fórmula matemática que está como String

Consegui fazer da seguinte forma:

    public boolean verificaQuantParentesesFormulAnual() {
        int n = -1;
        int n2 = -1;
        int nroVezesabre = 0;
        int nroVezesfecha = 0;
        String formula = crudObj.getFormulaAvaliacao().toLowerCase();
        for (;; ++nroVezesabre) {
            n = formula.indexOf("(", n + 1);
            if (n == -1) {
                break;
            }
        }
        for (;; ++nroVezesfecha) {
            n2 = formula.indexOf(")", n2 + 1);
            if (n2 == -1) {
                break;
            }
        }
        if (nroVezesabre - nroVezesfecha != 0) {
            return false;
        } else {
            return true;
        }
    }

Só que daí ele só conta, e não empilha e desempilha os parênteses…Poderia dar uma ajuda para implementarmos isso? Ou é vantagem alterar a que mandei anteriormente?? Vlww

Pra que você quer empilhar os parênteses?

Ricardo, por quê você não deu uma olhada no que escrevi?

Você não precisa ficar validando essas coisas, basta avaliar a fórmula atribuindo zero à todas as notas.

Um exemplo besta:

[code]public class TesteScript {

public static void main(String[] args) {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager
.getEngineByName(“javascript”);

while (true) {
  Scanner scanner = new Scanner(System.in);
  System.out.println("Digite a fórmula");
  String formula = scanner.nextLine();

  Bindings bindings = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE);
  bindings.put("np1", 0);
  bindings.put("np2", 0);
  bindings.put("np3", 0);
  bindings.put("np4", 0);

  try {
    scriptEngine.eval(formula);
  } catch (ScriptException e) {
    System.out.println("Fórmula inválida");
  }
  System.out.println("Fórmula válida");
}

}

}[/code]

Isso pode validar qualquer maluquice que o usuário digitar como fórmula (só não irá tratar casos de divisão por zero, mas você pode dar uma arrumada pra prevenir isso).

Não queria empilhar eles, mas…Por exemplo, se o cara digitar os parênteses em lugares onde não deveriam estar…
Por exemplo, oque fiz em C++ foi para o seguinte exercício:


Daí que pensei assim…Alguma idéia de como fazer para verificar entao se o cara não digitou os parêntese no lugar onde nao deveria??

Não queria empilhar eles, mas…Por exemplo, se o cara digitar os parênteses em lugares onde não deveriam estar…
Por exemplo, oque fiz em C++ foi para o seguinte exercício:


Daí que pensei assim…Alguma idéia de como fazer para verificar entao se o cara não digitou os parêntese no lugar onde nao deveria??[/quote]
Siga a sugestão do Ataxexe :slight_smile: É o que eu faria hehehe.

Tente avaliar a expressão, se der certo, é uma expressão válida

Não queria empilhar eles, mas…Por exemplo, se o cara digitar os parênteses em lugares onde não deveriam estar…
Por exemplo, oque fiz em C++ foi para o seguinte exercício:


Daí que pensei assim…Alguma idéia de como fazer para verificar entao se o cara não digitou os parêntese no lugar onde nao deveria??[/quote]
Siga a sugestão do Ataxexe :slight_smile: É o que eu faria hehehe.

Tente avaliar a expressão, se der certo, é uma expressão válida[/quote]
hehehe, blz, vou ver como fazer a que o Ataxexe falou … Vlww

Não queria empilhar eles, mas…Por exemplo, se o cara digitar os parênteses em lugares onde não deveriam estar…
Por exemplo, oque fiz em C++ foi para o seguinte exercício:


Daí que pensei assim…Alguma idéia de como fazer para verificar entao se o cara não digitou os parêntese no lugar onde nao deveria??[/quote]
Siga a sugestão do Ataxexe :slight_smile: É o que eu faria hehehe.

Tente avaliar a expressão, se der certo, é uma expressão válida[/quote]
Bom dia Rodrigo, tudo certo ?? Bem, testei a sugestão do jeito do Ataxexe e funcionou.Abaixo a maneira como fiz:

    public boolean verificaFormulAnual() throws ScriptException {
        String formula = crudObj.getFormulaAvaliacao();

        String REGEX = "(np\\d)";
        Double[] notas = {9.5, 9.3, 8.0, 8.8};

        StringBuffer novaFormula = new StringBuffer();
        Matcher buscador = Pattern.compile(REGEX).matcher(formula);

        int i = 0;
        while (buscador.find()) {
            buscador.appendReplacement(novaFormula, String.valueOf(notas[i++]));
        }
        buscador.appendTail(novaFormula);
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("javascript");
        Bindings bindings = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE);
        Object resultado = scriptEngine.eval(novaFormula.toString());

        if (resultado != null) {
            return true;
        } else {
            return false;
        }
    }

Mas, se eu quizer passar somente para testar um único valor para todas as notas ? ( pq nao sei qual a fórmula que a pessoa vai digitar. Então eu queria setar para todas as notas um único valor ao invés de um vetor de notas…Poderia dar uma ajuda aí?? Vlw

Mais uma vez: leia o código que postei.

As notas devem ser atribuídas pelos bindings e não por uma regexp:

Bindings bindings = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE); bindings.put("np1", 0); bindings.put("np2", 0); bindings.put("np3", 0); bindings.put("np4", 0);

E, se a fórmula for inválida sintaticamente, não será retornado null, será lançada uma exceção, que você deve tratar para retornar se a fórmula é válida ou inválida.

try { scriptEngine.eval(formula); } catch (ScriptException e) { System.out.println("Fórmula inválida"); } System.out.println("Fórmula válida");

Com algumas pequenas adaptações no código que postei você resolve seu problema. Eu tenho minhas dúvidas se esse seu código irá funcionar (a menos que você esteja capturando ScriptException para tratar.

Verificar o retorno da fórmula é uma adaptação válida para testar se não há algo de errado (você pode, por exemplo, atribuir a nota máxima para cada prova e testar se o valor da fórmula estará dentro do aceitável - seria estranho um aluno obter de média 8 com todas as notas 10). Você poderia até quebrar isso em dois passos: um para verificar sintaticamente a fórmula e outro para testar se ela está coesa.

[quote=Ataxexe]Mais uma vez: leia o código que postei.

As notas devem ser atribuídas pelos bindings e não por uma regexp:

Bindings bindings = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE); bindings.put("np1", 0); bindings.put("np2", 0); bindings.put("np3", 0); bindings.put("np4", 0);

E, se a fórmula for inválida sintaticamente, não será retornado null, será lançada uma exceção, que você deve tratar para retornar se a fórmula é válida ou inválida.

try { scriptEngine.eval(formula); } catch (ScriptException e) { System.out.println("Fórmula inválida"); } System.out.println("Fórmula válida");

Com algumas pequenas adaptações no código que postei você resolve seu problema. Eu tenho minhas dúvidas se esse seu código irá funcionar (a menos que você esteja capturando ScriptException para tratar.

Verificar o retorno da fórmula é uma adaptação válida para testar se não há algo de errado (você pode, por exemplo, atribuir a nota máxima para cada prova e testar se o valor da fórmula estará dentro do aceitável - seria estranho um aluno obter de média 8 com todas as notas 10). Você poderia até quebrar isso em dois passos: um para verificar sintaticamente a fórmula e outro para testar se ela está coesa.[/quote]
Bom dia Ataxexe , tdo certo cara? Bem, consegui fazer da seguinte maneira:

    public boolean verificaCoerenciaFormulAnual() throws ScriptException {
        String formulaAnual = crudObj.getFormulaAvaliacao();

        String REGEX = "(np\\d)";
        // Double[] notas = {9.5, 9.3, 8.0, 8.8};

        StringBuffer novaFormula = new StringBuffer();
        Matcher buscador = Pattern.compile(REGEX).matcher(formulaAnual);

        // int i = 0;
        while (buscador.find()) {
            buscador.appendReplacement(novaFormula, "10.0");
        }
        buscador.appendTail(novaFormula);
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("javascript");
        Bindings bindings = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE);
        Object resultado = scriptEngine.eval(novaFormula.toString());

        if (resultado != null) {
            return true;
        } else {
            return false;
        }
    }

A princípio funcionou…Agora estou vendo para testar outra fórmula, pois tenho a fórmula que pode contem nt e ne… Daí estou tentando usar assim:

 String REGEX = "(nt\\d|ne\\d)";
...ou
 String REGEX = "(n[te]\\d)";

Só que n]ao está dando certo, pq ele não tá conseguindo montar a fórmula.Estou fazendo da mesma maneira do que fiz anteriormente…Poderia dar uma ajuda aí? Vlwww

Não queria empilhar eles, mas…Por exemplo, se o cara digitar os parênteses em lugares onde não deveriam estar…
Por exemplo, oque fiz em C++ foi para o seguinte exercício:


Daí que pensei assim…Alguma idéia de como fazer para verificar entao se o cara não digitou os parêntese no lugar onde nao deveria??[/quote]
Siga a sugestão do Ataxexe :slight_smile: É o que eu faria hehehe.

Tente avaliar a expressão, se der certo, é uma expressão válida[/quote]
Estou tentando fazer o seguinte para quando tenho a seguinte formula ( nt + ne) / 2 :

    public boolean verificaCoerenciaFormulFinal() throws ScriptException {
        String formulaFinal = crudObj.getFormulAvalMediaFinal();
        // Exemplo de formula = (nt + ne)/2
        String REGEX = "(n[te]\\d)";
      
        StringBuffer novaFormula = new StringBuffer();
        Matcher buscador = Pattern.compile(REGEX).matcher(formulaFinal);

        while (buscador.find()) {
            buscador.appendReplacement(novaFormula, "10.0");
        }
        buscador.appendTail(novaFormula);
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("javascript");
        Bindings bindings = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE);
        Object resultado = scriptEngine.eval(novaFormula.toString());

        if (resultado != null) {
            return true;
        } else {
            return false;
        }
    }

Porém, ele não está conseguindo reconhecer e substituir…Poderia dar uma ajuda aí?? vLWW…

Cara, se não tem o número, tem que tirar o \d :slight_smile: Isso indica que vai ter um número hehehe

Meu deusss!!! E eu aqui me batendo hehehehe…Mto obrigado pela ajuda aí Rodrigo, Vlw msm…
Também agradeço o aadario ( meu professor da universidade :slight_smile: ) e o Ataxexe Vlwwww

Boa tarde Rodrigo, tudo certo ?? Cara, preciso de uma ajuda novamente…
Antes, eu podia fazer o seguinte:

  Pattern p = Pattern.compile("(\\d*|[+*/().-]|n[te]|\\s+)*");

Só que agora eu tbm quero digitar por exemplo np seguido de algum número na mesma fórmula. Tentei da seguinte maneira e nao obtive sucesso:

  Pattern p = Pattern.compile("(\\d*|[+*/().-]|n[te]| np\\d+|\\s+)*");

Poderia dar uma ajuda aí ?? Se puder ajudar, agradeço mto…Vlw

Tem um espaço ali no meio… Tire ele dali

Pattern p = Pattern.compile("(\\d*|[+*/().-]|n[te]|np\\d+|\\s+)*");

Só que ele está deixando passar nt1 por exemplo…O problema estaria aki???

   private boolean formulaAvalMediaFinalVerdadeira() {
        Pattern p = Pattern.compile("(\\d*|[+*/().-]|n[te]|np\\d+|\\s+)*");
        Matcher m = p.matcher(crudObj.getFormulAvalMediaFinal());
        return m.matches();
    }


  public boolean verificaCoerenciaFormulFinal() throws ScriptException {
        String formulaFinal = crudObj.getFormulAvalMediaFinal();
        String REGEX = "(n[te]|np\\d)";
        StringBuffer novaFormulaFinal = new StringBuffer();
        Matcher buscador = Pattern.compile(REGEX).matcher(formulaFinal);

        while (buscador.find()) {
            buscador.appendReplacement(novaFormulaFinal, "10.0");
        }
        buscador.appendTail(novaFormulaFinal);
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("javascript");
        Bindings bindings = scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE);
        Object resultadoFinal = scriptEngine.eval(novaFormulaFinal.toString());

        if (resultadoFinal != null) {
            return true;
        } else {
            return false;
        }
    }

Mais precisamente aki:

String REGEX = "(n[te]|np\\d)";

Nao estou conseguindo resolver…Se puder continuar ajudando, agradeço…Vlww cara

Ele permite porque você colocou um \d* no começo. Isso permite qualquer número, em qualquer lugar. Então ficou meio confusa sua regex :slight_smile: Vai ter que repensá-la

Poderia dar uma ajuda com isso cara?? To apanhando a horas feio com ela já…Ela pode ter nt e ne SEM NÚMEROS mas tbm pode ter np COM números…Se puder ajudar, agradeceria mto Rodrigo…Vlw

Vamos lá, vou te dar umas dicas, mas não vou fazer pra você :slight_smile:

\d -> Qualquer número
\D -> Qualquer coisa que não seja um número

As letras seriam as letras mesmo

[quote=Rodrigo Sasaki]Vamos lá, vou te dar umas dicas, mas não vou fazer pra você :slight_smile:

\d -> Qualquer número
\D -> Qualquer coisa que não seja um número

As letras seriam as letras mesmo[/quote]
vou tentar fazer aki, daki a poco posto o resultado…Vlw cara…

[quote=Rodrigo Sasaki]Vamos lá, vou te dar umas dicas, mas não vou fazer pra você :slight_smile:

\d -> Qualquer número
\D -> Qualquer coisa que não seja um número

As letras seriam as letras mesmo[/quote]
Cara, to tentando da seguinte maneira:

Pattern p = Pattern.compile("(\\d|[+*/().-]|\\D|n[te]|np\\d+|\\s+)*");

Tentei tbm:

Pattern p = Pattern.compile("(\\D|[+*/().-]|\\d|n[te]|np\\d+|\\s+)*");

E coloquei também parênteses entre meio…Mas não estou conseguindo…Poderia dar mais alguma dica ou ajuda?? Se puder ajudar, agradeço mtoo…To apanhando msm…Vlw cara…