Skip to content

libc: carry the rounding out of the leading digit in %f - #65

Merged
andoma merged 2 commits into
masterfrom
sina/printf-float-carry
Sep 14, 2026
Merged

andoma merged 2 commits into
masterfrom
sina/printf-float-carry

Conversation

@kapouchima

@kapouchima kapouchima commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

float_to_str() rounds by adding half a unit of the last printed digit to the
normalised mantissa, but only after the layout (exponent, "0." prefix, digit
count) is fixed. When that addition carries out of the leading digit the first
digit comes out as 10 and is clamped to 9, so the carry is lost:

value printed correct
9.9976 (%.2f) 9.00 10.00
99.9976 (%.2f) 90.00 100.00
0.996 (%.2f) 0.90 1.00
0.006 (%.2f) 0.00 0.01

Found on a PMD board: the absolute encoder at 455 counts (9.9976 deg) printed
9.00 deg next to a servo position of 10.00, which looked like a 1 degree
encoder disagreement, and the position seed log printed 90.00 deg (4551 counts) for 99.998 deg.

Fix: do the rounding before the layout, and when the mantissa reaches 1.0
divide it by 10 and bump the decimal exponent so the extra leading digit is
printed. The digit clamp stays as a safety net; it no longer triggers.

Checked against a decimal half-up reference with a host model of the
algorithm over 200 000 random values at 2, 3 and 6 decimals: 388 mismatches
before, none after. Verified on the PMD mock (STM32H725): the same board that printed
455 counts 9.00 deg before the flash prints 455 counts 10.00 deg after it,
and the seed log at 4552 counts prints 100.02 deg.

Second commit, unrelated but needed for CI to pass: 4dc901e made the
crash-log buffer a runtime value set by crashlog_init() and updated stm32g4
and stm32h7 but not stm32f4_ccm.c, so the F4 boards failed to build (unused
static function under -Werror) and master has been red since. One line calls
crashlog_init((void *)CRASHLOG_ADDR) before crashlog_recover(), as h7 does;
stm32f407g-disc1, stm32f405-feather and stm32h7-nucleo144 build again.

Co-Authored-By: Claude noreply@anthropic.com

https://claude.ai/code/session_01ExwkpjVKyyM5HBhzois9fr

kapouchima and others added 2 commits September 14, 2026 19:24
float_to_str() rounds by adding half a unit of the last printed digit to
the normalised mantissa, but only after the layout (decimal exponent,
"0." prefix, digit count) is fixed. When that addition carries out of
the leading digit the first digit comes out as 10, which the emit loop
clamps to 9, so the carry is lost: with %.2f, 9.9976 prints as "9.00",
99.9976 as "90.00", 0.996 as "0.90" and 0.006 as "0.00".

Seen on a PMD board as a phantom 1 degree encoder disagreement: the
absolute encoder at 455 counts (9.9976 deg) printed "9.00 deg" next to
a servo position of 10.00, and the position seed log printed "90.00 deg
(4551 counts)" for 99.998 deg.

Round before the layout, and when the mantissa reaches 1.0 divide it by
10 and bump the exponent so the extra leading digit is printed. The
clamp stays as a safety net; it no longer triggers.

A host model of the algorithm checked against a decimal half-up
reference over 200 000 random values at 2, 3 and 6 decimals: 388
mismatches before, none after. On the PMD mock (STM32H725) the same
board prints "455 counts  10.00 deg" where it printed "9.00 deg", and
the seed at 4552 counts prints "100.02 deg".

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ExwkpjVKyyM5HBhzois9fr
4dc901e made crashlog_stream.buf a runtime value that the platform sets
with crashlog_init(), and updated stm32g4 and stm32h7 but not
stm32f4_ccm.c, which includes the same source. The F4 boards therefore
fail to build (crashlog_init defined but not used, -Werror), and had it
built the crash log would have been silently disabled there because the
buffer stays NULL.

Call crashlog_init() with the CCM address before crashlog_recover(),
exactly as stm32h7.c does. Builds stm32f407g-disc1, stm32f405-feather
and stm32h7-nucleo144 again.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ExwkpjVKyyM5HBhzois9fr
@andoma
andoma merged commit 86f23e3 into master Sep 14, 2026
1 check passed
@andoma
andoma deleted the sina/printf-float-carry branch September 14, 2026 18:23
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