Wie in anderen Antworten zu dieser Frage erwähnt, hat JDK 8 in der DecimalFormat
Rundung absichtliche Änderungen in Ausgabe JDK-7131459: DecimalFormat produces wrong format() results when close to a tie vorgenommen.
Allerdings haben diese Änderungen ein echten Fehler eingeführt, der als JDK-8039915: Wrong NumberFormat.format() HALF_UP rounding when last digit exactly at rounding position greater than 5 gemeldet wurde. Zum Beispiel:
99.9989 -> 100.00
99.9990 -> 99.99
Um es einfach auszudrücken, hier wird ein Fall demonstriert, in dem eine höhere Zahl abgerundet wird und eine niedrigere Zahl aufgerundet: (x <= y) != (round(x) <= round(y))
. Dies scheint nur den Rundungsmodus HALF_UP
zu betreffen, der die Art der Rundung ist, die in der Grundschularithmetik gelehrt wird: 0,5 wird immer weg von Null gerundet.
Dieses Problem tritt in Oracle- und OpenJDK-Veröffentlichungen von Java 8 und Updates 8u5, 8u11, 8u20, 8u25 und 8u31 auf.
Oracle hat diesen Fehler in Java 8 Update 40 behoben
Ein inoffizieller Laufzeit-Patch ist für frühere Versionen verfügbar
Dank der Recherche von Holger in dieser Antwort zu einer verwandten Frage konnte ich einen Laufzeit-Patch entwickeln und mein Arbeitgeber hat ihn kostenlos unter den Bedingungen der GPLv2-Lizenz mit Classpath-Ausnahme veröffentlicht1 (gleich wie der OpenJDK-Quellcode).
Das Patch-Projekt und der Quellcode sind auf GitHub gehostet mit weiteren Details zu diesem Fehler sowie Links zu herunterladbaren Binärdateien. Der Patch funktioniert zur Laufzeit, sodass keine Änderungen an den Java-Dateien auf der Festplatte vorgenommen werden, und er sollte auf allen Versionen von Oracle Java >= 6 und zumindest bis Version 8 (einschließlich u40 und später) sicher sein.
1 Ich bin kein Anwalt, aber mein Verständnis ist, dass GPLv2 w/ CPE die kommerzielle Nutzung in binärer Form ermöglicht, ohne dass die GPL auf das kombinierte Werk angewendet wird.