View Full Version : [JAVA] (0.35+0.05) = 0.39999999999999997!!!
JohnMarston
01-11-2015, 21:54
Ciao a tutti, ho notato che provando a fare questo calcolo ottengo un valore che mi sta facendo impazzire.
System.out.println("calcolo: "+(0.35+0.05));
Output:
calcolo: 0.39999999999999997
Io devo ottenere 0.40. Se in un ciclo for io incremento una variabile di +0.05, quando quest'ultima assumerà il valore 0.35, sommando l'incremento, io ottengo 0.39999999999999997...
Il che non va bene perché all'interno dello stesso ciclo io ho una condizione simile a questa:
if(variabileIncrementata==0.40){....
E come potete immaginare non mi entra perché la variabile contiene questo valore 0.39999999999999997!!!
Non posso neanche mettere
if(variabileIncrementata<=0.40)
oppure
if(variabileIncrementata>=0.40)
la variabile incriminata deve per forza darmi 0.40.
Cosa suggerite di fare??
Grazie
JohnMarston
01-11-2015, 22:26
purtroppo non posso lavorare con le tolleranze... Il valore dev'essere preciso.
Stavo pensado ad un arrotondamento.
Benvenuto nel mondo dei floating point, il tuo "problema" è assolutamente la norma quando si ha a che fare con questo tipo di dato.
Come dice bene Antonio23, definisci a piacere un valore di soglia per il check, es 0.0001, e fai il controllo se la differenza del tuo valore con il valore limite è minore della soglia di tolleranza :)
Don[ITA]
02-11-2015, 10:16
Potresti anche provare a lavorare con BigDecimal invece che con i float :)
JohnMarston
02-11-2015, 15:00
ho fatto alcuni test, neanche arrotondando va bene....
Tolleranza... Che tipo di tolleranza devo mettere??
variabile <=0.0000000001 variabile >=0.00000001
Che pacco....
una cosa del tipo (pseudo codice eh)
static const float THRESHOLD = 0.00001;
...
if ( abs (0.40 - variabileIncrementata) < THRESHOLD)
{
//fai quello che devi fare
}
...
Daniels118
03-11-2015, 13:09
Con i numeri in virgola mobile può accadere anche di peggio:
System.out.println(1000000f + 0.001f);
Stampa 1000000.0
Se la precisione non è importante ma si vuole garantire l'avanzamento di un loop si può optare per quest'altro approccio:
float step = 0.05f
for (int i = 0; i < 8; i++) {
float valore = (float) i * step;
//...
}
Nel tuo caso andrebbe bene, infatti:
System.out.println(8f * 0.05f);
Stampa 0.4
JohnMarston
03-11-2015, 14:20
Eccolo qui il mio problemone!
public class TestDouble {
private static double tmpRange=-0.05, maxRange=0.45;
private static double step=0.05;
private static double[] array={-0.05, 0.10, 0.15, 0.40, 0.45 };
public static void main(String[] args) throws Exception{
while(tmpRange<=maxRange){
for(int x=0; x<array.length; x++){
if(tmpRange== array[x]){
System.out.println("CONDIZIONE: tmpRange "+ tmpRange+" è uguale a elemento array n: "+x+" ("+array[x]+")");
}
}
System.out.println("while() valori tmpRange: "+tmpRange);
tmpRange+=step;
}
}
}
Ho molti dubbi riguardo alla "tolleranza" perché lo step che ora assume il valore di 0.05, cambia! Potrebbe essere 0.01 come 0.20 oppure 0.005... È variabile!
Output:
CONDIZIONE: tmpRange -0.05 è uguale a elemento array n: 0 (-0.05)
while() valori tmpRange: -0.05
while() valori tmpRange: 0.0
while() valori tmpRange: 0.05
CONDIZIONE: tmpRange 0.1 è uguale a elemento array n: 1 (0.1)
while() valori tmpRange: 0.1
while() valori tmpRange: 0.15000000000000002
while() valori tmpRange: 0.2
while() valori tmpRange: 0.25
while() valori tmpRange: 0.3
while() valori tmpRange: 0.35
while() valori tmpRange: 0.39999999999999997
while() valori tmpRange: 0.44999999999999996
Come si può notare quando array è 0.15, 0.40, 0.45 non entra... :mad:
Daniels118
03-11-2015, 15:02
Intendi dire che lo step varia durante l'esecuzione del ciclo?
Se lo step non cambia durante l'esecuzione puoi adottare il metodo che ho indicato, va bene anche se il ciclo non è calcolato:
public class TestDouble {
private static double startRange=-0.05, maxRange=0.45;
private static double step=0.05;
private static double[] array={-0.05, 0.10, 0.15, 0.40, 0.45 };
public static void main(String[] args) throws Exception{
double tmpRange;
int i = 0;
while (tmpRange <= maxRange) {
tmpRange = startRange + ((double) i) * step;
for(int x=0; x<array.length; x++){
if(tmpRange== array[x]){
System.out.println("CONDIZIONE: tmpRange "+ tmpRange+" è uguale a elemento array n: "+x+" ("+array[x]+")");
}
}
System.out.println("while() valori tmpRange: "+tmpRange);
i++;
}
}
}
cdimauro
03-11-2015, 17:57
La tolleranza dipende strettamente dalla dimensione/ampiezza dei numeri manipolati.
JohnMarston
03-11-2015, 20:52
in base ai vostri consigli sono riuscito a risolvere (credo, spero..)...
ci si aggiorna qualora saltasse fuori qualcosa di anomalo nel mio codice!
grazie!
Daniels118
04-11-2015, 08:38
Ovvero? Come hai risolto?
JohnMarston
05-11-2015, 17:06
Ho preso spunto dal tuo codice. Grazie!
vBulletin® v3.6.4, Copyright ©2000-2026, Jelsoft Enterprises Ltd.