DecimalFormat rounding changes in 8 (JEP 177)?
Bernd
ecki at zusammenkunft.net
Mon May 5 07:59:27 UTC 2014
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-libs at 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.
>>
>>
>
More information about the core-libs-dev
mailing list