PDA

Visualizza la versione completa : [JAVA] Comportamento anomalo in esecuzione codice traccia d'esame


Pierfrank
18-02-2012, 18:06
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:


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:


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" ??

Pierfrank
18-02-2012, 18:11
Scusatemi non ho visto la sottosezione di Java, se qualche mod può spostare gentilmente o riapro io

ramy89
18-02-2012, 20:56
C'è sempre un errore di macchina nelle operazioni di somma tra floating point.
Più i numeri sono vicini (come grandezza), più l' errore è piccolo.
Dipende anche dai dati, un numero può non avere la sua rappresentazione esatta, ma arrotondata.
Puoi sempre risolvere usando la printf di System.out per stampare una cifra sola:



System.out.printf("%1$.1f", s);


Oppure usare DecimalFormat (http://docs.oracle.com/javase/1.4.2/docs/api/java/text/DecimalFormat.html).

MItaly
18-02-2012, 21:33
1.1 non ha una rappresentazione esatta in binario, per cui viene usato un valore approssimato. Per questo e altri motivi non si confrontano mai dei numeri in virgola mobile per uguaglianza, ma si verifica che la loro differenza sia inferiore ad un certo epsilon.
Per ulteriori informazioni sulla questione puoi leggere questo famoso articolo (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html).

Pierfrank
18-02-2012, 22:49
Originariamente inviato da MItaly
1.1 non ha una rappresentazione esatta in binario, per cui viene usato un valore approssimato. Per questo e altri motivi non si confrontano mai dei numeri in virgola mobile per uguaglianza, ma si verifica che la loro differenza sia inferiore ad un certo epsilon.
Per ulteriori informazioni sulla questione puoi leggere questo famoso articolo (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html).

Pierfrank
18-02-2012, 22:50
Originariamente inviato da Pierfrank
ah ecco...capito il problema, è proprio la virgola, quindi qualsiasi decimale, che non esiste in numero binario

Loading