RFR: 8370013: Refactor Double.toHexString to eliminate regex and StringBuilder [v2]

Raffaello Giulietti rgiulietti at openjdk.org
Mon Oct 20 14:18:08 UTC 2025


On Mon, 20 Oct 2025 06:34:39 GMT, Shaojin Wen <swen at openjdk.org> wrote:

>> This PR refactors the Double.toHexString method to improve its performance by eliminating the use of StringBuilder and regex operations. The new implementation uses a direct byte array approach to construct the hex string representation, which avoids the overhead of StringBuilder operations and regex pattern matching.
>> 
>> Existing tests in `java/lang/Double/ToHexString.java`.
>
> Shaojin Wen has updated the pull request incrementally with one additional commit since the last revision:
> 
>   from @jddarcy

src/java.base/share/classes/java/lang/Double.java line 711:

> 709:             // For infinity and NaN, use the decimal output.
> 710:             return Double.toString(d);
> 711:         else {

Remove the `else` (but of course, not the code)

src/java.base/share/classes/java/lang/Double.java line 713:

> 711:         else {
> 712:             boolean negative = Math.copySign(1.0, d) == -1.0;
> 713:             d = Math.abs(d);

Move this down, after the check for `0.0`.

src/java.base/share/classes/java/lang/Double.java line 717:

> 715:             if (d == 0.0) {
> 716:                 return negative ? "-0x0.0p0" : "0x0.0p0";
> 717:             } else {

As above, remove the `else`.

src/java.base/share/classes/java/lang/Double.java line 724:

> 722:                 // so that the string representation has a known length.
> 723:                 // This ensures we always have 13 hex digits to work with (52 bits / 4 bits per hex digit)
> 724:                 long signifBits = (Double.doubleToLongBits(d)

Suggestion:

                long signifBits = Double.doubleToLongBits(d) & DoubleConsts.SIGNIF_BIT_MASK;


plus the change below.

src/java.base/share/classes/java/lang/Double.java line 732:

> 730:                 // We limit to 12 because we want to keep at least 1 hex digit (13 total - 12 = 1)
> 731:                 // assert 0 <= trailingZeros && trailingZeros <= 12
> 732:                 int trailingZeros = Math.min(12, ((Long.numberOfTrailingZeros(signifBits) & 0xFC) >> 2));

Suggestion:

                int trailingZeros = Long.numberOfTrailingZeros(signifBits | 1L << 4 * 12) >> 2;

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/27811#discussion_r2445142978
PR Review Comment: https://git.openjdk.org/jdk/pull/27811#discussion_r2445143666
PR Review Comment: https://git.openjdk.org/jdk/pull/27811#discussion_r2445143853
PR Review Comment: https://git.openjdk.org/jdk/pull/27811#discussion_r2445144092
PR Review Comment: https://git.openjdk.org/jdk/pull/27811#discussion_r2445144567


More information about the core-libs-dev mailing list