DecimalFormat rounding changes in 8 (JEP 177)?

olivier.lagneau at oracle.com olivier.lagneau at oracle.com
Mon May 5 08:22:34 UTC 2014


On 05/05/2014 09:59, Bernd wrote:
> 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).
Initial bug Number in JDK7 is JDK-7131459:
https://bugs.openjdk.java.net/browse/JDK-7131459

related JDK8 bug is :
https://bugs.openjdk.java.net/browse/JDK-8000978

Hth,
Olivier
>
> 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