Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8065885

DecimalFormat percentInstance HALF_UP wrong rounding down on doubles greater but close to tie

XMLWordPrintable

    • generic
    • generic

      FULL PRODUCT VERSION :
      java version "1.8.0_40-ea"
      Java(TM) SE Runtime Environment (build 1.8.0_40-ea-b15)
      Java HotSpot(TM) Client VM (build 25.40-b18, mixed mode, sharing)

      also reproduced on 1.8.0-25

      ADDITIONAL OS VERSION INFORMATION :
      Windows 7 Enterprise SP 1

      A DESCRIPTION OF THE PROBLEM :
      The DecimalFormat percent-formatter produces the wrong result when rounding-halves up for a double representing 12.235% i.e. 0.12235.

      Please note that this is not a symptom of the Java 8 bug fix to round values close to "a half" based on their internal representation. Assuming the value displayed by BigDecimal.toString is a correct representation of the internals of the "double", the internal value of the problem number is actually slightly larger than 0.12235, so even with the Java 8 fix, this value should "round up".

      REGRESSION. Last worked in version 7u51

      ADDITIONAL REGRESSION INFORMATION:
      java version "1.7.0_45"
      Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
      Java HotSpot(TM) Client VM (build 24.45-b08, mixed mode, sharing)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the Demo program in English Locale.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Double is 0.12235
      Internal representation is larger than this... 0.12235000000000000042188474935755948536098003387451171875
       ...but DecimalFormat rounds down 12.24%
       ...can work around by formatting the BigDecimal 12.24%


      ACTUAL -
      Double is 0.12235
      Internal representation is larger than this... 0.12235000000000000042188474935755948536098003387451171875
       ...but DecimalFormat rounds down 12.23%
       ...can work around by formatting the BigDecimal 12.24%

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      public class Demo
      {
         public static void main( final String[] args )
         {
            final NumberFormat nf = DecimalFormat.getPercentInstance();
            nf.setMinimumFractionDigits( 2 );
            nf.setMaximumFractionDigits( 2 );
            nf.setRoundingMode( RoundingMode.HALF_UP );
            final double problem = 0.122350d; // expect this to round up to 12.24%
            System.out.println("Double is " + problem );
            System.out.println( "Internal representation is larger than this... " + new BigDecimal(problem));
            System.out.println(" ...but DecimalFormat rounds down " + nf.format(problem) );
            System.out.println(" ...can work around by formatting the BigDecimal " + nf.format(new BigDecimal(problem)) );
         }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      As shown in the code, wrapping the double in a BigDecimal before formatting seems to work around the problem.

            nishjain Nishit Jain
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            7 Start watching this issue

              Created:
              Updated:
              Resolved: