Se usi double
o float
, dovresti usare l'arrotondamento o aspettarti di vedere alcuni errori di arrotondamento. Se non puoi farlo, usa BigDecimal
.
Il problema che hai è che 0.1 non è una rappresentazione esatta e, eseguendo il calcolo due volte, stai aggravando quell'errore.
Tuttavia, 100 possono essere rappresentati accuratamente, quindi prova:
double x = 1234;
x /= 100;
System.out.println(x);
che stampa:
12.34
Funziona perché Double.toString(d)
esegue una piccola quantità di arrotondamenti per tuo conto, ma non è molto. Se ti stai chiedendo come potrebbe essere senza arrotondamento:
System.out.println(new BigDecimal(0.1));
System.out.println(new BigDecimal(x));
stampe:
0.100000000000000005551115123125782702118158340454101562
12.339999999999999857891452847979962825775146484375
In breve, l'arrotondamento è inevitabile per risposte sensate in virgola mobile, indipendentemente dal fatto che lo si faccia esplicitamente o meno.
Nota: x / 100
e x * 0.01
non sono esattamente gli stessi quando si tratta di errore di arrotondamento. Questo perché l'errore di arrotondamento per la prima espressione dipende dai valori di x, mentre quello 0.01
della seconda ha un errore di arrotondamento fisso.
for(int i=0;i<200;i++) {
double d1 = (double) i / 100;
double d2 = i * 0.01;
if (d1 != d2)
System.out.println(d1 + " != "+d2);
}
stampe
0.35 != 0.35000000000000003
0.41 != 0.41000000000000003
0.47 != 0.47000000000000003
0.57 != 0.5700000000000001
0.69 != 0.6900000000000001
0.7 != 0.7000000000000001
0.82 != 0.8200000000000001
0.83 != 0.8300000000000001
0.94 != 0.9400000000000001
0.95 != 0.9500000000000001
1.13 != 1.1300000000000001
1.14 != 1.1400000000000001
1.15 != 1.1500000000000001
1.38 != 1.3800000000000001
1.39 != 1.3900000000000001
1.4 != 1.4000000000000001
1.63 != 1.6300000000000001
1.64 != 1.6400000000000001
1.65 != 1.6500000000000001
1.66 != 1.6600000000000001
1.88 != 1.8800000000000001
1.89 != 1.8900000000000001
1.9 != 1.9000000000000001
1.91 != 1.9100000000000001