Skip to content

Fix precision formatting of long double values just below a power of 10 - #5010

Merged
vitaut merged 2 commits into
fmtlib:mainfrom
ShawnNotFound:fix-long-double-precision-near-pow10
Nov 8, 2026
Merged

vitaut merged 2 commits into
fmtlib:mainfrom
ShawnNotFound:fix-long-double-precision-near-pow10

Conversation

@ShawnNotFound

Copy link
Copy Markdown
Contributor

For some 80-bit long double values just below a power of 10, formatting with a precision gives a leading zero or rounds at the wrong digit:

auto ld = std::ldexp(static_cast<long double>(0xe596b7b0c643c719ULL), 79);
fmt::format("{:.19e}", ld);  // "1.0000000000000000000e+43", expected "9.9999999999999999997e+42"
fmt::format("{:.21g}", ld);  // "0.99999999999999999997e+43"
fmt::format("{:.0f}", ld);   // "09999999999999999999741184793924429452148736"

format_dragon estimates the exponent and corrects it in the dragon::fixup step, but that check also includes the upper boundary when a precision is given, so the estimate isn't lowered and the digits are generated one exponent too high. The upper boundary only matters in the shortest mode, where the output can round up to the next power of 10. With a fixed number of digits, rounding happens after digit generation, so this compares only the value in that case. Shortest output is unchanged.

The same thing happens for double when it's formatted at compile time, e.g. 9.9999999999999992e22 with {:.20e} gave 0.99999999999999991611e+23.

Added the cases above to the precision test. I also compared 200k random long double values against printf with {:.Ne} and {:.Nf} and found no differences.

format_dragon included the upper boundary when checking whether the
estimated exponent is one too high. This is needed for the shortest
output, but with a given precision it left a leading zero digit, so
values such as nextafter(1e43L, 0) were printed with an extra digit in
fixed notation or a mantissa below 1 in exponent notation.
@ShawnNotFound
ShawnNotFound requested a review from vitaut as a code owner November 2, 2026 23:59

@vitaut vitaut left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good but please apply clang-format.

@ShawnNotFound

Copy link
Copy Markdown
Contributor Author

Thanks, applied clang-format.

@vitaut
vitaut merged commit 9c19ea4 into fmtlib:main Nov 8, 2026
47 checks passed
@vitaut

vitaut commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Merged, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants