java round - Dezimalstellen in Doppelschritten verschieben




5 Answers

Wenn Sie double oder float , sollten Sie eine Rundung verwenden oder einige Rundungsfehler erwarten. Wenn dies nicht möglich ist, verwenden Sie BigDecimal .

Das Problem, das Sie haben, ist, dass 0.1 keine exakte Darstellung ist, und indem Sie die Berechnung zweimal durchführen, komplementieren Sie diesen Fehler.

100 kann jedoch genau dargestellt werden, also versuchen Sie es:

double x = 1234;
x /= 100;
System.out.println(x);

welches druckt:

12.34

Dies funktioniert, weil Double.toString(d) in Ihrem Namen eine kleine Rundung durchführt, 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, ist eine Rundung für sinnvolle Antworten im Fließkomma-Punkt unumgänglich, ob Sie dies explizit tun oder nicht.

Hinweis: x / 100 und x * 0.01 sind beim Rundungsfehler nicht genau gleich. Dies liegt daran, dass der Rundungsfehler für den ersten Ausdruck von den Werten von x abhängt, während der 0.01 für den 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);
}

Drucke

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
double to

Also habe ich einen doppelten Satz, der 1234 entspricht, ich möchte eine Dezimalstelle verschieben, um 12,34 zu machen

Um das zu tun, multipliziere ich zweimal 1 bis 1234, so ähnlich

double x = 1234;
for(int i=1;i<=2;i++)
{
  x = x*.1;
}
System.out.println(x);

Dies wird das Ergebnis "12.340000000000002" drucken

Gibt es einen Weg, den Doppelpunkt 12.34 korrekt zu speichern, ohne ihn einfach auf zwei Dezimalstellen zu formatieren?




Wenn es nur formatiert wird, versuchen Sie es mit printf

    double x = 1234;
    for(int i=1;i<=2;i++)
    {
      x = x*.1;
    }
    System.out.printf("%.2f",x);

Ausgabe

12.34



Sie können eine Ganzzahldarstellung versuchen

int i =1234;
int q = i /100;
int r = i % 100;

System.out.printf("%d.%02d",q, r);



Lustig, dass zahlreiche Beiträge erwähnen, BigDecimal zu verwenden, aber niemand stört, um die richtige Antwort basierend auf BigDecimal zu geben? Denn auch mit BigDecimal können Sie immer noch schief gehen, wie dieser Code zeigt

String numstr = "1234";
System.out.println(new BigDecimal(numstr).movePointLeft(2));
System.out.println(new BigDecimal(numstr).multiply(new BigDecimal(0.01)));
System.out.println(new BigDecimal(numstr).multiply(new BigDecimal("0.01")));

Gibt diese Ausgabe

12.34
12.34000000000000025687785232264559454051777720451354980468750
12.34

Der BigDecimal-Konstruktor erwähnt ausdrücklich, dass es besser ist, den String-Konstruktor als einen numerischen Konstruktor zu verwenden. Ultimative Präzision wird auch durch den optionalen MathContext beeinflusst.

Gemäß dem BigDecimal Javadoc ist es möglich , ein BigDecimal zu erstellen, das genau gleich 0,1 ist, vorausgesetzt, Sie verwenden den String-Konstruktor.




Nein, als Java Gleitkommatypen (in der Tat alle Fließkommatypen) sind ein Kompromiss zwischen Größe und Genauigkeit. Obwohl sie für viele Aufgaben sehr nützlich sind, sollten Sie BigDecimal verwenden, wenn Sie eine beliebige Genauigkeit benötigen.




Related

java double decimal