Wenn Sie double
oder verwenden float
, sollten Sie Rundungen verwenden oder erwarten, dass Rundungsfehler auftreten. Wenn Sie dies nicht tun können, verwenden Sie BigDecimal
.
Das Problem, das Sie haben, ist, dass 0.1 keine exakte Darstellung ist. Wenn Sie die Berechnung zweimal durchführen, verschärfen Sie diesen Fehler.
100 können jedoch genau dargestellt werden. Versuchen Sie also:
double x = 1234;
x /= 100;
System.out.println(x);
welche druckt:
12.34
Dies funktioniert, weil Double.toString(d)
in Ihrem Namen eine kleine Rundung durchgeführt wird, aber es ist nicht viel. Wenn Sie sich fragen, wie es ohne Rundung aussehen könnte:
System.out.println(new BigDecimal(0.1));
System.out.println(new BigDecimal(x));
Drucke:
0.100000000000000005551115123125782702118158340454101562
12.339999999999999857891452847979962825775146484375
Kurz gesagt, eine Rundung ist für sinnvolle Antworten im Gleitkomma unvermeidlich, unabhängig davon, ob Sie dies explizit tun oder nicht.
Hinweis: x / 100
und x * 0.01
sind nicht genau gleich, wenn es um Rundungsfehler geht. Dies liegt daran, dass der Rundungsfehler für den ersten Ausdruck von den Werten von x abhängt, während der 0.01
im zweiten Ausdruck einen festen Rundungsfehler aufweist.
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);
}
druckt
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