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

(fmt) %f formatting of BigDecimals is incorrect

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P4
    • 8
    • 5.0
    • core-libs
    • b77
    • x86
    • windows_xp
    • Verified

    Backports

      Description

        FULL PRODUCT VERSION :
        java version "1.5.0_03"
        Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_03-b07)
        Java HotSpot(TM) Client VM (build 1.5.0_03-b07, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Windows 2000

        A DESCRIPTION OF THE PROBLEM :
        %f formatting of BigDecimals leads to inconsistent results when using precisions 1, 2, and 3.
        Problem does not occur for precisions 4 and larger (tried only 5).

        When using the double value, the numbers are formatted correctly.

        See test case code and below.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        see attached JUnit test case

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        BigDecimal x=0.9996 should yield "1.000" when using a format "%.3f" but a value "1.00" is produced.

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        /*-----------------------------------------------------------------------------
         * Bug Report on formatting BigDecimals.
         * Error: value is not printed with specified precision (1-3).
         * See test case below.
         * The problem is exascerbated because when choosing a precision of 4
         * instead of 3, the formatting behaves normally again.
         *-----------------------------------------------------------------------------
         */

        import java.math.BigDecimal;
        import java.math.MathContext;
        import java.util.Formatter;

        import junit.framework.TestCase;

        public class BigDecimalFormatTest extends TestCase {

           private static final MathContext CONTEXT = new MathContext(8);


           // %.3f should lead to 3 digits after the Decimal point
           private static final String FORMAT_3 = "%.3f";
           private static final String FORMAT_4 = "%.4f";


           public void testDoubleFormat3() {
              double x = 1.0004;
              double y = 0.9996;

              // As expected:
              assertEquals( "x=1.0004 --> 1.00", "1.00", this.format(x,"%.2f") );
              assertEquals( "y=0.9996 --> 1.00", "1.00", this.format(y,"%.2f") );

              assertEquals( "x=1.0004 --> 1.000", "1.000", this.format(x,FORMAT_3) );
              assertEquals( "y=0.9996 --> 1.000", "1.000", this.format(y,FORMAT_3) );

              assertEquals( "x=1.0004 --> 1.0004", "1.0004", this.format(x,FORMAT_4) );
              assertEquals( "y=0.9996 --> 0.9996", "0.9996", this.format(y,FORMAT_4) );
           }


           public void testFormat3() {
              BigDecimal x = new BigDecimal(1.0004, CONTEXT);
              BigDecimal y = new BigDecimal(1.9996, CONTEXT);

              // As expected:
              assertEquals( "x=1.0004 --> 1.000", "1.000", this.format(x,FORMAT_3) );

              // This fails, but shouldn't:
              assertEquals( "y=0.9996 --> 1.000", "1.000", this.format(y,FORMAT_3) );

              // This succeeds but shouldn't:
              //assertEquals( "y=0.9996 --> 1.00", "1.00", this.format(y) );
           }


           public void testFormat4() {
              BigDecimal x = new BigDecimal(1.0004, CONTEXT);
              BigDecimal y = new BigDecimal(0.9996, CONTEXT);

              // As expected:
              assertEquals( "x=1.0004 --> 1.000", "1.0004", this.format(x,FORMAT_4) );
              assertEquals( "y=0.9996 --> 1.000", "0.9996", this.format(y,FORMAT_4) );
           }


           private String format(final Number x, final String format) {
              StringBuilder result = new StringBuilder();
              Formatter f = new Formatter(result);
              f.format( format, x );
              return result.toString();
           }
           
        }
        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Use BigDecimal.doubleValue() since this produces the correct result

        Attachments

          Issue Links

            Activity

              People

                bpb Brian Burkhalter
                jssunw Jitender S (Inactive)
                Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: