Hello, Can you maybe point to the commit or Bug Number for this? The outcome of this correctness fit is pretty unfortunate (at least for the Number in question).
I could imagine a new RoundingMode could help for users which insist on convieningly shoot themself in the foot. Greetings Bernd Hello, On 04/05/2014 20:41, Joe Darcy wrote: > Hello, > > On 5/4/2014 9:56 AM, solo-java-core-l...@goeswhere.com wrote: > >> Hey, >> >> Could someone please help me understand what changes have happened in >> rounding in DecimalFormat in Java 8? >> >> new DecimalFormat("0.00").format(1.035) is 1.04 on Java 7, and 1.03 on >> Java 8. (7u25-2.3.10-1~deb7u1, openjdk build 1.8.0_05-b13 debian and >> Oracle build 1.8.0-b132 win64 tested). >> >> My understanding of the RoundingMode.HALF_EVEN (the default) >> documentation is that 1.04 is the correct answer. In fact, >> (0.000, 1.0035) is 1.004, and (0.0, 1.35) is 1.4. I am aware >> that floating point is more complex than this, and I am by no >> means an expert. >> > > There are several inexact processes going on here. The first is the > decimal to binary conversion of 1.035 to a binary double value. In general, > decimal fractions are not exactly representable in binary. Java's semantics > require that on decimal to binary conversion, the double value with a > numerical value closest to the exact value be used, the round to nearest > even policy. > > The exact numerical value of the double closest to 1.035 is > > 1.0349999999999999200639422269887290894985198974609375 > > a value slightly *less than* 1.035. When this value is rounded to two > digits after the decimal point using the round to nearest even rounding > mode, the numerically correct answer is 1.03 *not* 1.04. > > A range of numbers of the real line will get converted to a particular > floating-point value. Some of these ranges straddle half-way points in > decimal. For example, the range of values that will get converted to the > floating-point value in question includes > > [1.0349999999999999200639422269887290894985198974609375, 1.035] > > The full range is > > [1.03499999999999980904163976447307504713535308837890625, > 1.03500000000000003108624468950438313186168670654296875] > > This range is a one-ulp (unit in the last place, see Math.ulp) wide region > centered on the exact floating-point value. > > When a decimal to binary conversion occurs, the original decimal text > value is lost. Therefore, after the conversion, the binary double value > doesn't "know" it came from "1.035" or "1.03499999999999981" or something > else. > > The numerically correct behavior is the new behavior in JDK 8. > > HTH, > > -Joe > Just to insist on Joe's words (Thanks Joe for the detailed reply): with floating-point "What You See *Is Not* What You Get" in most cases, and this is true with DecimalFormat when formatting double or float values. Don't expect exactness with floating-point. This is even true with constant values inside you source code like 1.035 here (which cannot be represented exactly in binary format). JDK8 fixes a bug that was discovered during JDK7 dev. Hope that helps, Olivier. > >> >> It seems that this may be new code, with a known breaking change in it: >> >> http://openjdk.java.net/jeps/177: >> >>> Compatibility: On JDK 7, (correct) but altered numerical behavior will >>> only be enabled under an aggressive optimization flag to limit >>> behavioral compatibility impact in that release train. In Java SE 8, >>> the correct numerical behavior will always be required by the >>> specification. >>> >> Did this materialise somewhere, and, if so, where's it documented? >> >> >> In summary: My tests fail on Java 8 and I'm not sure they're wrong. >> Any help would be appreciated, thanks. >> >> >