Formatting BigDecimal("0.50") using DecimalFormat with RoundingMode.HALF_UP and maximumFractionDigits 0 return 0 instead of 1

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      Property settings:
          file.encoding = UTF-8
          file.separator = /
          java.class.path =
          java.class.version = 69.0
          java.home = /home/user/.sdkman/candidates/java/25.0.1-tem
          java.io.tmpdir = /tmp
          java.library.path = /usr/java/packages/lib
              /usr/lib64
              /lib64
              /lib
              /usr/lib
          java.runtime.name = OpenJDK Runtime Environment
          java.runtime.version = 25.0.1+8-LTS
          java.specification.name = Java Platform API Specification
          java.specification.vendor = Oracle Corporation
          java.specification.version = 25
          java.vendor = Eclipse Adoptium
          java.vendor.url = https://adoptium.net/
          java.vendor.url.bug = https://github.com/adoptium/adoptium-support/issues
          java.vendor.version = Temurin-25.0.1+8
          java.version = 25.0.1
          java.version.date = 2025-10-21
          java.vm.compressedOopsMode = Zero based
          java.vm.info = mixed mode, sharing
          java.vm.name = OpenJDK 64-Bit Server VM
          java.vm.specification.name = Java Virtual Machine Specification
          java.vm.specification.vendor = Oracle Corporation
          java.vm.specification.version = 25
          java.vm.vendor = Eclipse Adoptium
          java.vm.version = 25.0.1+8-LTS
          jdk.debug = release
          line.separator = \n
          native.encoding = UTF-8
          os.arch = amd64
          os.name = Linux
          os.version = 6.8.0-90-generic
          path.separator = :
          stderr.encoding = UTF-8
          stdin.encoding = UTF-8
          stdout.encoding = UTF-8
          sun.arch.data.model = 64
          sun.boot.library.path = /home/user/.sdkman/candidates/java/25.0.1-tem/lib
          sun.cpu.endian = little
          sun.io.unicode.encoding = UnicodeLittle
          sun.java.launcher = SUN_STANDARD
          sun.jnu.encoding = UTF-8
          sun.management.compiler = HotSpot 64-Bit Tiered Compilers

      openjdk version "25.0.1" 2025-10-21 LTS
      OpenJDK Runtime Environment Temurin-25.0.1+8 (build 25.0.1+8-LTS)
      OpenJDK 64-Bit Server VM Temurin-25.0.1+8 (build 25.0.1+8-LTS, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      When using DecimalFormat to format a BigDecimal with value 0.50 it returns 0 instead of 1. I will try to explain how the code behaves:

      When DecimalFormat.format() is called the DigitList.set() is called. DigitList sets the value count to 2 (there are 2 digits), digits array to [5, 0, �, �, �, �, �, �, �, �, �, �, �, �, �, �, �, �, �], decimalAt to 0. This triggers the if statement that should decide to round up:
      if (shouldRoundUp(0, roundedUp, valueExactAsDecimal))

      Instead of true the shouldRoundUp method returns false.

      The shouldRoundUp method enters the switch statement with HALF_UP and digits[maximumDigits] == 5 true.

      below if statement is false because maximum digits is not equal to count -1 (0 == 1 is false)
      // Rounding position is the last index, there are 3 Cases.
      if (maximumDigits == (count - 1)) {}

      the else statement goes to the to nonZeroAfterIndex(maximumDigits+1). This checks if there's any non zeros in the digits array. This is also false because it starts from index 1 which is the 0 and there are no other digits.

      The conclusion of shouldRoundUp is false which is incorrect

      REGRESSION : Last worked in version 21.0.9

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      DecimalFormat decimalFormat = new DecimalFormat(); decimalFormat.setMaximumFractionDigits(0); decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
      BigDecimal value = new BigDecimal("0.50");
      String shouldBeOne = decimalFormat.format(value);
      assertThat(shouldBeOne, is("1"));

      ---------- BEGIN SOURCE ----------
      @Test
      void decimalFormatTest() {
      DecimalFormat decimalFormat = new DecimalFormat(); decimalFormat.setMaximumFractionDigits(0); decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
      BigDecimal value = new BigDecimal("0.50");
      String shouldBeOne = decimalFormat.format(value);
      assertThat(shouldBeOne, is("1"));
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      create an if statement to check if the BigDecimal to format is equal to new BigDecimal("0.50"). if true call the formatter with value.setScale(1, HALF_UP)

      FREQUENCY :
      ALWAYS

        1. Test.java
          0.6 kB
          Patricia Tavares

            Assignee:
            Patricia Tavares
            Reporter:
            Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: