Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 13
  1. #1

    [JAVA] Comportamento anomalo in esecuzione codice traccia d'esame

    Ho riaperto qui


    Salve, credo che per questo problema ci voglia una persona con più conoscenza in campo. Allora, se vi scrivo è perchè ho trovato una stranezza usando Eclipse per compilare ed eseguire un codice che fa parte di una traccia d'esame, infatti fra poco avrò l'esame all'università e vorrei togliermi gli ultimi dubbi su quanto riguarda i fondamenti di Java.
    Il programma è questo:

    codice:
    public class PariDisp{ 
    public static void main(String [] args){ 
    double [] [] mat = new double[][]{{1.0,2.0,2.1,1.1},
     {1.0,1.5,1.5,1.0}, 
    {1.1,3.3,3.2,1.0}, 
    {1.1,2.0,2.0,1.1}};
     if(metodo2(mat)) 
    System.out.println("OK"); 
    else System.out.println("NON OK");
     } 
    public static double metodo1(double[] v, int i){
     double s=0;
     for(int k=i;k<v.length;k+=2)
     s+=v[k];
     return s;
     }
     public static boolean metodo2(double [] [] m){
     boolean verificato=true; 
    for(int k=0;k<m.length && verificato;k++)
     if(metodo1(m[k],0)!=metodo1(m[k],1))
     verificato=false; 
    return verificato;
     }
    }
    In pratica il programma restituisce "OK" se la somma degli elementi in posizione pari è uguale alla somma degli elementi in posizione dispari di ogni riga della matrice "m[][]"...il risultato è stato stranamente "NON OK" perchè mi dice che nella terza riga le somme degli elementi dispari e pari non sono uguali.
    Allora per capire il problema ho fatto una prova di collaudo, cioè ho riscritto il codice con il "System.out.print" nella zona interessata per vedere qual'era l'errore:

    codice:
    public class PariDisp {
     public static void main(String [] args){
     double[][]mat=new double[][]{{1.0,2.0,2.1,1.1},
     {1.0,1.5,1.5,1.0},
     {1.1,3.3,3.2,1.0},
     {1.1,2.0,2.0,1.1}};
     if(metodo2(mat)) System.out.println("OK");
     else System.out.println("NON OK");
     }
     public static double metodo1(double[] v,int i){
     double s=0; 
    for(int k=i;k<v.length;k+=2){ s+=v[k];
     System.out.println(v[k]);
     }
     System.out.println("La somma è uguale a "+s);
     return s;
     } 
    public static boolean metodo2(double [][]m){
     boolean verificato=true;
     for(int k=0;k<m.length && verificato;k++) 
    if(metodo1(m[k],0)!=metodo1(m[k],1)) 
    verificato=false; 
    return verificato; 
    } 
    }

    Ed ecco il risultato in Eclipse:

    1.0
    2.1
    La somma è uguale a 3.1
    2.0
    1.1
    La somma è uguale a 3.1
    1.0
    1.5
    La somma è uguale a 2.5
    1.5
    1.0
    La somma è uguale a 2.5
    1.1
    3.2
    La somma è uguale a 4.300000000000001
    3.3
    1.0
    La somma è uguale a 4.3
    NON OK

    Come viene fuori quel "4.300000000000001" ??

  2. #2
    1.1 è il classico errore che riguarda la rappresentazione dei numeri decimali. In java i double sono numeri rappresentati in doppia precisione (quindi in binario). Essendo rappresentati in binario, numeri come 1.1 o 0.3 non possono essere trasformati in binario e si usa pertanto un arrotondament. Avresti avuto gli stessi problemi con qualunque linguaggio di programmazione.

    Ciao

  3. #3
    Utente di HTML.it
    Registrato dal
    Aug 2002
    Messaggi
    8,013
    usa i tag CODE per postare codice.

    Le operazioni in virgola mobile hanno quella caratteristica, non c'è molto da fare. Più o meno è così da circa 40 anni. Se ti ostini ad usare double, allora conviene che il check tu non lo faccia sull'uguaglianza, ma piuttosto sulla dimensione che la differenza tra i due valori da confrontare sia più o meno piccola.

    Con int invece non hai alcun problema.
    <´¯)(¯`¤._)(¯`»ANDREA«´¯)(_.¤´¯)(¯`>
    "The answer to your question is: welcome to tomorrow"

  4. #4
    Originariamente inviato da Gotchabest
    1.1 è il classico errore che riguarda la rappresentazione dei numeri decimali. In java i double sono numeri rappresentati in doppia precisione (quindi in binario). Essendo rappresentati in binario, numeri come 1.1 o 0.3 non possono essere trasformati in binario e si usa pertanto un arrotondament. Avresti avuto gli stessi problemi con qualunque linguaggio di programmazione.

    Ciao
    ti ringrazio per la spiegazione ma ancora non mi è chiaro perchè java debba fare a forza questo arrotondamento, che tra l'altro fa solo con alcuni numeri decimali, non con tutti.
    però vabè almeno so che l'errore non l'ho fatto io ma è il modo di ragionare di java

  5. #5
    Originariamente inviato da Andrea1979
    usa i tag CODE per postare codice.

    Le operazioni in virgola mobile hanno quella caratteristica, non c'è molto da fare. Più o meno è così da circa 40 anni. Se ti ostini ad usare double, allora conviene che il check tu non lo faccia sull'uguaglianza, ma piuttosto sulla dimensione che la differenza tra i due valori da confrontare sia più o meno piccola.

    Con int invece non hai alcun problema.
    questa era una traccia d'esame del 2006 e non mi spiegavo perchè non dava il risultato corretto..però vabè il senso mi è più o meno chiaro

  6. #6
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219

  7. #7
    Originariamente inviato da ramy89
    Ti ho risposto nel primo post:

    http://forum.html.it/forum/showthrea...0#post13562060
    però sarebbe inutile il printf perchè java sbaglierebbe comunque i calcoli contenuti nel metodo e non darebbe il risultato esatto

  8. #8
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219
    Allora l' unico modo è aumentare la precisione.
    Si "sbagliano" sempre i calcoli, in realtà è un arrotondamento.
    Il valore pigreco si potrebbe rappresentare esattamente solo con precisione infinita.
    Quasi sicuramente c'è qualche classe java che tratta i numeri in virgola mobile usando una maggiore precisione.

  9. #9
    Originariamente inviato da ramy89
    Allora l' unico modo è aumentare la precisione.
    Si "sbagliano" sempre i calcoli, in realtà è un arrotondamento.
    Il valore pigreco si potrebbe rappresentare esattamente solo con precisione infinita.
    Quasi sicuramente c'è qualche classe java che tratta i numeri in virgola mobile usando una maggiore precisione.
    credo che l'unica cosa sia usare float che non dovrebbe arrotondare

  10. #10
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219
    Originariamente inviato da Pierfrank
    credo che l'unica cosa sia usare float che non dovrebbe arrotondare


    Ma proprio non capisci, è impossibile.
    Non si hanno infiniti bit a disposizione per rappresentare un float, come fa a non arrotondare?
    Studiati come funzionano i floating point a doppia precisione IEEE 754.
    Ti ha pure risposto MItaly nel post duplicato:
    http://forum.html.it/forum/showthrea...4#post13562074

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 © 2025 vBulletin Solutions, Inc. All rights reserved.