-
Type:
Bug
-
Resolution: Duplicate
-
Priority:
P3
-
None
-
Affects Version/s: 25
-
Component/s: core-libs
-
generic
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
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
- duplicates
-
JDK-8369050 DecimalFormat Rounding Errors for Fractional Ties Near Zero
-
- Resolved
-