Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    [Java] Svolgimento delle Operazioni: Miglioramento del codice?

    Per allenamento, perche' potrebbe servirmi e per ostinazione forse sto tentando da me di fare un risolutore di espressioni in linguaggio Java.

    Vi posto il codice. Se volete aiutarmi a renderlo un programma funzionante a tutti gli effetti...

    Il programma computa "bene" la stringa di esempio, ma fallisce in numerosi altri casi.

    Soprattutto con le funzioni sin(...) e cos(...) dove i valori cambiano di segno.

    Inoltre dovrebbe essere in grado, e per ora ovviamente non lo e' di eseguire funzioni di funzioni(come sqr(sqrt(...)))

    Un problema e' dovuto al segno "-" quando l'espressione sopratutto di trova a non svolgere calcoli perche ha piu' di un segno in sequenza come 2.0*-3.0, inoltre si dovrebbe gestire 2.0*(-3.0)^2

    Il primo problema invece: risulta dal fatto che e' necessario per il parse double come vedete evidenziare le cifre dopo la virgola: (2.0 anziche' 2)

    Qui trovate il codice:
    http://tpcg.io/_CRLPPK




    Ben vengano consigli...

    Buona serata...
    jabjoint

  2. #2
    Quote Originariamente inviata da jabjoint Visualizza il messaggio
    Per allenamento, perche' potrebbe servirmi e per ostinazione forse sto tentando da me di fare un risolutore di espressioni in linguaggio Java.
    Scusa ma ... il Nashorn non andava bene?

    Questo l'ho scritto velocemente:
    codice:
    import javax.script.Bindings;
    import javax.script.Compilable;
    import javax.script.CompiledScript;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    public class Prova {
        public static void main(String[] args) throws ScriptException {
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("Nashorn");
    
            CompiledScript compiledExpr = ((Compilable) engine).compile("3*Math.pow(x, 2) - 15*x + 20");
            Bindings bindings = engine.createBindings();
    
            for (double x = 0; x <= 10; x += 0.1) {
                bindings.put("x", x);
                double result = (double) compiledExpr.eval(bindings);
                System.out.printf("x=%.5f --> %f%n", x, result);
            }
        }
    }

    Giusto alcune note:

    Compilable è una interfaccia che un ScriptEngine può opzionalmente implementare (non è obbligatorio). Il Nashorn la implementa. In questo modo si può "precompilare" l'espressione in modo che sia ri-eseguibile molto velocemente. Chiaramente il compile può fallire con ScriptException. Non l'ho gestita bene solo per brevità.

    Con il Bindings si possono "iniettare" valori nella espressione. Ho scritto una espressione matematica pensata a caso (equazione di 2° grado).

    Funziona sia con il Nashorn built-in del JDK che con quello messo come dipendenza esplicita (es. con Maven).


    Quote Originariamente inviata da jabjoint Visualizza il messaggio
    Vi posto il codice. Se volete aiutarmi a renderlo un programma funzionante a tutti gli effetti...

    Il programma computa "bene" la stringa di esempio, ma fallisce in numerosi altri casi.
    Non l'ho letto tutto in dettaglio .... ma a me sembra scritto un po' maluccio (e fumoso). Sia stilisticamente, sia per cose non molto appropriate tipo if (numero!="")

    Per fare un parser di espressioni matematiche si dovrebbero applicare i concetti che portano alla creazione di un "albero" di nodi, come è descritto qui:

    https://www.openbookproject.net/book...ParseTree.html

    Quindi, in sostanza, se NON hai applicato un concetto del genere ...... hai totalmente sbagliato approccio.
    Andrea • andbin.dev
    Senior Java developerSCJP 5 (91%) – SCWCD 5 (94%)

  3. #3
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Scusa ma ... il Nashorn non andava bene?

    Questo l'ho scritto velocemente:
    codice:
    import javax.script.Bindings;
    import javax.script.Compilable;
    import javax.script.CompiledScript;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    public class Prova {
        public static void main(String[] args) throws ScriptException {
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("Nashorn");
    
            CompiledScript compiledExpr = ((Compilable) engine).compile("3*Math.pow(x, 2) - 15*x + 20");
            Bindings bindings = engine.createBindings();
    
            for (double x = 0; x <= 10; x += 0.1) {
                bindings.put("x", x);
                double result = (double) compiledExpr.eval(bindings);
                System.out.printf("x=%.5f --> %f%n", x, result);
            }
        }
    }

    Giusto alcune note:

    Compilable è una interfaccia che un ScriptEngine può opzionalmente implementare (non è obbligatorio). Il Nashorn la implementa. In questo modo si può "precompilare" l'espressione in modo che sia ri-eseguibile molto velocemente. Chiaramente il compile può fallire con ScriptException. Non l'ho gestita bene solo per brevità.

    Con il Bindings si possono "iniettare" valori nella espressione. Ho scritto una espressione matematica pensata a caso (equazione di 2° grado).

    Funziona sia con il Nashorn built-in del JDK che con quello messo come dipendenza esplicita (es. con Maven).



    Non l'ho letto tutto in dettaglio .... ma a me sembra scritto un po' maluccio (e fumoso). Sia stilisticamente, sia per cose non molto appropriate tipo if (numero!="")

    Per fare un parser di espressioni matematiche si dovrebbero applicare i concetti che portano alla creazione di un "albero" di nodi, come è descritto qui:

    https://www.openbookproject.net/book...ParseTree.html

    Quindi, in sostanza, se NON hai applicato un concetto del genere ...... hai totalmente sbagliato approccio.
    Ciao andbin, intanto grazie tante per le risposte, solo ora riesco a risponderti, si sicuramente ci deve essere un iterazione ricorsiva ad albero (nodi),
    per quanto riguarda le funzioni sopratutto(sin(sin(sin...)))), poi per il resto il fatto di usare il "replace" per le parentesi semplifica sicuramente il calcolatore, ma non so ben se è una strada stabile o se anche qui è richiesta una richiamata ricorsiva di altro genere. Per le operazioni le svolge se trova un operatore tra due numeri in sequenza nella stringa.
    Grazie del link lo vedrò al più presto.
    Purtroppo non sono ancora riuscito a caricare il nashorn da te postato, tento di nuovo ora, siccome mi premeva vedere i risultati, inoltre per diletto e passione mi sono un pochino dedicato a questo tipo di "risolutore", so bene che non è un buon motore ancora.

    Per:
    codice:
    if (numero!="")
    l'ho applicato perché il numero vien costruito come Stringa(Per poi ritornare un valore double, che però vien accettato solo se scritto nella forma: cifre.decimali , infatti potrebbe essere una lettera anche, di "sin" ad esempio.

    Tu come avresti fatto?
    codice:
    if (numero.length()>0)
    ?

    Ultima modifica di jabjoint; 20-09-2022 a 22:02
    jabjoint

  4. #4
    Quote Originariamente inviata da jabjoint Visualizza il messaggio
    Purtroppo non sono ancora riuscito a caricare il nashorn da te postato
    NON basta avere solo il nashorn-core-15.4.jar (preso es. dal Maven Central).
    Il nashorn-core ha diverse "dipendenze" (5 altri jar, per la precisione). Quindi servono tutti quelli.

    Ecco perché usare Maven/Gradle è moooolto più preferibile rispetto ad altre soluzioni "manuali".
    Andrea • andbin.dev
    Senior Java developerSCJP 5 (91%) – SCWCD 5 (94%)

  5. #5
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,235
    Quote Originariamente inviata da jabjoint Visualizza il messaggio
    Per:
    codice:
    if (numero!="")
    l'ho applicato perché il numero vien costruito come Stringa
    E le stringhe sono oggetti.
    E gli oggetti NON si confrontano usando gli operatori relazionali ( == e != ) ma usando il metodo equals().

    Prova questo: anche se premi invio senza scrivere nulla non otterrai mai di entrare nel ramo ELSE.
    codice:
    import java.util.Scanner;
    
    public class StringaVuota {
       public static void main(String[] args) {
          try (Scanner sc = new Scanner(System.in)) {
             System.out.print("Digita l'input seguito da INVIO: ");
             String line = sc.nextLine();
             if (line != "") {
                System.out.println("Hai inserito una stringa NON vuota. Lunghezza: " + line.length());
             } else {
                System.out.println("Hai inserito la stringa vuota");
             }
          } catch (Exception e) {
              e.printStackTrace();
          }
       }
    }

    Ciao.
    Ultima modifica di LeleFT; 21-09-2022 a 10:51
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  6. #6
    Quote Originariamente inviata da LeleFT Visualizza il messaggio
    E le stringhe sono oggetti.
    E gli oggetti NON si confrontano usando gli operatori relazionali ( == e != ) ma usando il metodo equals().

    Prova questo: anche se premi invio senza scrivere nulla non otterrai mai di entrare nel ramo ELSE.
    codice:
    import java.util.Scanner;
    
    public class StringaVuota {
       public static void main(String[] args) {
          try (Scanner sc = new Scanner(System.in)) {
             System.out.print("Digita l'input seguito da INVIO: ");
             String line = sc.nextLine();
             if (line != "") {
                System.out.println("Hai inserito una stringa NON vuota. Lunghezza: " + line.length());
             } else {
                System.out.println("Hai inserito la stringa vuota");
             }
          } catch (Exception e) {
              e.printStackTrace();
          }
       }
    }

    Ciao.
    Verissimo.
    Scusate la bruttissima svista...
    jabjoint

  7. #7
    Quote Originariamente inviata da andbin Visualizza il messaggio
    NON basta avere solo il nashorn-core-15.4.jar (preso es. dal Maven Central).
    Il nashorn-core ha diverse "dipendenze" (5 altri jar, per la precisione). Quindi servono tutti quelli.

    Ecco perché usare Maven/Gradle è moooolto più preferibile rispetto ad altre soluzioni "manuali".
    Ho tentato di usare Mavel e da lì imposto le 3 variabili(dipendenze). Non parte.

    Comunque si NON avevo nemmeno usato l'incapsulamento in quel brutto "CODICE", che ripeto ho creato anche per imparare un pochino "meglio"...
    jabjoint

  8. #8
    Quote Originariamente inviata da jabjoint Visualizza il messaggio
    Ho tentato di usare Mavel e da lì imposto le 3 variabili(dipendenze). Non parte.
    pom.xml
    codice:
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    
        <modelVersion>4.0.0</modelVersion>
        <groupId>tuo.gruppo</groupId>
        <artifactId>prova-nashorn</artifactId>
        <version>0.0.1</version>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.openjdk.nashorn</groupId>
                <artifactId>nashorn-core</artifactId>
                <version>15.4</version>
            </dependency>
        </dependencies>
    
    </project>

    Cambia pure groupId/artifactId/version (quelli sotto modelVersion) e eventualmente versione di Java se non usi la 17.
    Ma fatto questo e messo nei sorgenti quel sorgente Prova che ho postato prima (con o senza package, non fa differenza) .... deve funzionare.
    Andrea • andbin.dev
    Senior Java developerSCJP 5 (91%) – SCWCD 5 (94%)

  9. #9
    Quote Originariamente inviata da andbin Visualizza il messaggio
    pom.xml
    codice:
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    
        <modelVersion>4.0.0</modelVersion>
        <groupId>tuo.gruppo</groupId>
        <artifactId>prova-nashorn</artifactId>
        <version>0.0.1</version>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.openjdk.nashorn</groupId>
                <artifactId>nashorn-core</artifactId>
                <version>15.4</version>
            </dependency>
        </dependencies>
    
    </project>

    Cambia pure groupId/artifactId/version (quelli sotto modelVersion) e eventualmente versione di Java se non usi la 17.
    Ma fatto questo e messo nei sorgenti quel sorgente Prova che ho postato prima (con o senza package, non fa differenza) .... deve funzionare.
    Grazie @andbin, ma il pom.xml va nella cartella src?

    Il "mio" programma, grazie alla mia ostinazione funziona abbastanza bene:

    Computa correttamente un' espressione come:
    expression = "12.0+3.0*sqrt(sin(tan(sqrt(12.0)+0.1)+0.1)+2.0*12 .0)^(abs(cos(1.4))+1.0/2.1)"

    devo risolvere ancora:

    *Difficolta

    *Penso facile:
    1) Controllo parentesi.
    2) Assegnazione costanti.
    3) Passaggio in input di valori non necessariamente double(non necessariamente terminanti con cifre dopo la virgola/punto)

    *Penso difficile:
    1) Gestione dei "Numeri negativi", in particolare operazioni del tipo in: (sgn num)^esp = (-2.0)^3 (rimanendo nei reali)
    Qui dovrei salvare il segno in una variabile, ad esempio in questo caso potrebbe fare:

    Per POTENZA:
    se il sgn=- allora toglie il segno computa l'operazione e lo rimette se esp � dispari nell' blocco dell'elevamento a potenza.�

    Per SOMMA(differenza) non ci sono problemi � sufficiente anteporre uno 0.0 prima del numero da sottrarre.

    Per MOLTIPLICAZIONE e DIVISIONE:
    computa -> expression = 0.0-4.0*5.0; quindi volendo anche: -4,0*5.0

    Non computa:
    num = -0,5*(-0.6) (Scritta cos� in modo corretto ovviamente)
    Quindi pensavo di salvare il segno ed esguire sempre l' abs(num), per poi anteporlo ed eseguire le relative trasformazioni algebriche:, se "-" � ,moltiplicato per n "-" dispari... o pari...prende le misure...

    Saluti e grazie.
    jabjoint

  10. #10
    Quote Originariamente inviata da jabjoint Visualizza il messaggio
    ma il pom.xml va nella cartella src?
    No. Un progetto Maven deve avere una struttura ben precisa, che a livello basilare è questa:

    codice:
    nome-progetto/
       pom.xml
       src/
          main/
             java/
                ...sorgenti Java...
             resources/
                ...risorse che finiscono in "classpath"...
          test/
             java/
                ...sorgenti Java di test...
             resources/
                ...risorse di test che finiscono nel classpath di test...

    Per poter usare Maven .. un minimo di conoscenza ci vuole ...
    Andrea • andbin.dev
    Senior Java developerSCJP 5 (91%) – SCWCD 5 (94%)

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2022 vBulletin Solutions, Inc. All rights reserved.