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

Incorrect data transformation in BigDecimal.valueOf(double) method

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      Windows 11, Java 21.0.3-9

      A DESCRIPTION OF THE PROBLEM :
      Problem simulated in simple jUnit test - in which it is displayed that with the usage of "BigDecimal.valueOf(double)" incorrect object is created (most likely due to the new way of 'toString' method in Double class)

      @Test
          void testDoubleConversion() {
              final String stringRepresentation = "0212467111917324511";
              // after the conversion to double value is 2.12467111917324512E17 (this is OK)
              final double parsedDouble = Double.parseDouble(stringRepresentation);
              // after conversion to string - value is: 2.124671119173245E17 (last two digits are lost due to the new way of toString method in the Double class)
              final String backFromDouble = Double.toString(parsedDouble);
              // conversion back to double brings again the original value: 2.12467111917324512E17
              final double parsedFromBackFromDouble = Double.parseDouble(backFromDouble);
              assertEquals(parsedDouble, parsedFromBackFromDouble);

              // with the usage of constructor BigDecimal holds the same value as parsedDouble: 212467111917324512
              final BigDecimal bigDecimalFromDouble = new BigDecimal(parsedDouble);
              System.out.println(bigDecimalFromDouble);
              // with the usage of valueOf(double) precession is lost due to the new 'toString' method in the Double class: 2.12467111917324512E17
              final BigDecimal bigDecimalFromValueOf = BigDecimal.valueOf(parsedDouble);
              System.out.println(bigDecimalFromValueOf);
              // compare fail due to the fact that 'bigDecimalFromDouble' is greater number (due to the lost of last 2 digits in 'valueOf' conversion)
              assertThat(bigDecimalFromDouble, Matchers.comparesEqualTo(bigDecimalFromValueOf));
          }

      REGRESSION : Last worked in version 17.0.11

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      jUnit which simulates the issue is added in Description

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Precession won't be lost during usage of "toString(double)" in BigDecimal class
      ACTUAL -
      Last two digits from the test are lost with the usage of toString(double) in BigDecimal class

      ---------- BEGIN SOURCE ----------

      @Test
          void testDoubleConversion() {
              final String stringRepresentation = "0212467111917324511";
              // after the conversion to double value is 2.12467111917324512E17 (this is OK)
              final double parsedDouble = Double.parseDouble(stringRepresentation);
              // after conversion to string - value is: 2.124671119173245E17 (last two digits are lost due to the new way of toString method in the Double class)
              final String backFromDouble = Double.toString(parsedDouble);
              // conversion back to double brings again the original value: 2.12467111917324512E17
              final double parsedFromBackFromDouble = Double.parseDouble(backFromDouble);
              assertEquals(parsedDouble, parsedFromBackFromDouble);

              // with the usage of constructor BigDecimal holds the same value as parsedDouble: 212467111917324512
              final BigDecimal bigDecimalFromDouble = new BigDecimal(parsedDouble);
              System.out.println(bigDecimalFromDouble);
              // with the usage of valueOf(double) precession is lost due to the new 'toString' method in the Double class: 2.12467111917324512E17
              final BigDecimal bigDecimalFromValueOf = BigDecimal.valueOf(parsedDouble);
              System.out.println(bigDecimalFromValueOf);
              // compare fail due to the fact that 'bigDecimalFromDouble' is greater number (due to the lost of last 2 digits in 'valueOf' conversion)
              assertThat(bigDecimalFromDouble, Matchers.comparesEqualTo(bigDecimalFromValueOf));
          }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      usage of "new BigDecimal(double)" instead of BigDecimal.valueOf(double) for Java 19 and above (most likely problem is caused by new implementation from https://bugs.openjdk.org/browse/JDK-4511638)

      FREQUENCY : always


            darcy Joe Darcy
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: