Ich möchte meine Zahl (gz) auf 3 Stellen nach dem Komma runden. Bei der Ausgabe wird aber immer auf ganze Zahlen gerundet. Wo ist der Fehler in meinem Code?

3 Antworten

Gleitpunktzahlen - zumindest die Sorte, von der wir hier reden - kannst du in sehr vielen Fällen sowieso nicht exakt runden.

Außerdem würde ich an deiner Stelle keinen ellenlangen Formel-Schwanz produzieren, sondern die eigentliche Berechnung und die Rundung in (mindestens) zwei getrennte Zeilen aufteilen.

Nach der Berechnung sähe eine Annäherung auf drei Nachkommastellen so aus:

gz = Math.round(gz * 1000.0) / 1000.0;

Aber nochmal, exakte Rundungen wirst du prinzipbedingt mit den gängigen Gleitpunkttypen Javas nicht hinbekommen können. (ob mit oder ohne "strictfp") Außerdem hängt das bei der IEEE 754 Repräsentation auch noch extrem stark vom eigentlichen Wert ab.

Java bietet eine genauere Klasse für Gleitpunktzahlen an, nämlich BigDecimal, die auch über mehr Rundungsmöglichkeiten verfügt, aaaaaber soweit ich mich recht erinnere, arbeitet diese Klasse intern nicht wie IEEE 754-2008, also dezimal, sondern binär, was eine exakte Rundung unmöglich macht.

Du müsstest dir also entweder eine eigene Klasse bauen (was gar nicht soooo schwer ist!) oder auf eine fertige Bibliothek zurück greifen. Allerdings dürfte für deinen Falle die Rundung aus dem Einzeiler-Snippet locker ausreichen, und man muss ja nicht mit Kanonen auf Spatzen schießen. :)

Naja, trotzdem viel Erfolg! :)

Dein Code ist nicht sonderlich gut.

  • Er ist nicht formatiert (falsche Einrückungen, fehlende Zeilenumbrüche).
  • Die Bezeichner sind nichtssagend.
  • Du splittest unnötig auf in Deklaration und Definition. Stattdessen könntest du mit Initialisierungen mehrere Zeilen sparen.
int number = 1;

Zu deinem Problem: Du rechnest mit Ganzzahlen.

gz = Math.round(1000 * (g * (1 + (z / 100)))) / 1000;

Die Division durch 1000 beispielsweise erzeugt zwar temporär eine Zahl mit Nachkommastelle, doch da alle anderen Operanden aus Ganzzahlen bestehen, findet ein impliziter Typecast statt. Für die Zuweisung gibt es wieder einen impliziten Typecast zu double, doch bis dahin wurde die Nachkommastelle bereits abgetrennt.

Mindestens einer der Operanden je Berechnung sollte eine Gleitkommazahl darstellen. Entweder du führst explizites Typecasting durch oder du verwendest entsprechende Literale:

gz = Math.round(1000 * ( g * (1 + (z / 100d)))) / 1000d;

Ich bin in Java nicht so firm, wie findet dort die Typumwanlung statt?

Ergibt ein int/1000 eine Fließkommazahl, oder müsste dies etwa durch int/1000.0 erzwungen werden?