Skip to content

Conversation

@josesimoes
Copy link
Member

@josesimoes josesimoes commented Oct 31, 2025

Description

  • Reworked rounding logic in nanoprintf
    • Reworked the rounding logic to use the actual rounding digit (pend) and propagate carry correctly from the last significant digit leftwards.
    • Properly handles ripple (e.g., 9.8999 -> 10) and updates decpt/ndigits when needed in FF_FCVT mode.
    • Handle edge case with precision and value as 0.
  • Handle negative 0 situation in Format_F.

Motivation and Context

How Has This Been Tested?

Screenshots

Types of changes

  • Improvement (non-breaking change that improves a feature, code or algorithm)
  • Bug fix (non-breaking change which fixes an issue with code or algorithm)
  • New feature (non-breaking change which adds functionality to code)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Config and build (change in the configuration and build system, has no impact on code or features)
  • Dev Containers (changes related with Dev Containers, has no impact on code or features)
  • Dependencies/declarations (update dependencies or assembly declarations and changes associated, has no impact on code or features)
  • Documentation (changes or updates in the documentation, has no impact on code or features)

Checklist

  • My code follows the code style of this project (only if there are changes in source code).
  • My changes require an update to the documentation (there are changes that require the docs website to be updated).
  • I have updated the documentation accordingly (the changes require an update on the docs in this repo).
  • I have read the CONTRIBUTING document.
  • I have tested everything locally and all new and existing tests passed (only if there are changes in source code).

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced floating-point number formatting accuracy and rounding precision in numerical output.

- Reworked the rounding logic to use the actual rounding digit (pend) and propagate carry correctly from the last significant digit leftwards.
- Properly handles ripple (e.g., 9.8999 -> 10) and updates decpt/ndigits when needed in FF_FCVT mode.
@josesimoes josesimoes added the Area: Common libs Everything related with common libraries label Oct 31, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 31, 2025

Walkthrough

Updates adjust floating-point rounding and precision handling in nanoprintf and add negative-zero trimming in System.Number native formatting. Rounding now uses the extra digit at pend with leftward carry propagation; zero-precision zero paths emit a single '0'. Native formatting removes a spurious minus for values that round to zero.

Changes

Cohort / File(s) Summary
Nanoprintf rounding & precision
src/CLR/Helpers/nanoprintf/nanoprintf.c
Rounding now inspects the extra generated digit at pend to decide rounding and propagates carries leftward from pend toward the first produced digit with a start boundary at buf+2. Handles rollover past the most-significant digit by incrementing that digit, adjusting decpt, and — in FCVT (fixed-float) mode — incrementing ndigits and pend. Adds explicit handling for precision==0 and value==0 to emit a single '0' and adjust zero-padding width.
Negative-zero handling in Number formatting
src/CLR/CorLib/corlib_native_System_Number.cpp
Introduces isNegative at outer scope and a branch that detects values that round to zero while originally negative; when detected, removes the leading '-' from the buffer and decrements the result length. Negativity detection was moved out of the integer-specific block for broader use.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Caller
participant nanoprintf
participant Formatter as System_Number
Note over Caller,nanoprintf: Formatting request with float value and precision
Caller->>nanoprintf: generate digits + extra digit at pend
nanoprintf-->>nanoprintf: decide rounding using digit at pend
alt rounding requires carry
nanoprintf-->>nanoprintf: propagate carry leftwards from pend to start (buf+2)
nanoprintf-->>nanoprintf: if carry rolls past MS digit, increment MS digit and adjust decpt
nanoprintf-->>nanoprintf: if FCVT mode, increment ndigits and shift pend
else simple rounding
nanoprintf-->>nanoprintf: increment last significant digit
end
nanoprintf-->>Caller: return formatted digits (handles precision==0 zero path)
Note over Caller,Formatter: Integer/native formatting path
Caller->>Formatter: receive formatted buffer
Formatter-->>Formatter: check isNegative and buffer contents
alt negative but rounds to zero
Formatter-->>Formatter: remove '-' and decrement length
end
Formatter-->>Caller: final string

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review carry propagation and pointer boundary logic in nanoprintf.c (especially start vs. buf+2 and MS rollover adjustments).
  • Verify FCVT-specific updates to ndigits and pend when rollover extends digit count.
  • Validate zero-precision zero emission and zero-padding width adjustments.
  • Inspect corlib_native_System_Number.cpp changes for edge cases (negative zero detection and buffer manipulations).

Possibly related issues

  • Fix UART timeouts configuration #1688: Fix tostring handling code to deal with ToString("N0") with doubles and floats — Changes to nanoprintf rounding/precision and negative-zero trimming in System.Number directly address formatting and rounding behaviors relevant to this issue.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues Check ✅ Passed The code changes directly address the requirements specified in linked issue #1688. The rounding logic updates in nanoprintf.c fix the core problem where values like 9.8999 should round to 10 but were not handling this correctly, by using the actual rounding digit and properly propagating carry leftwards. The modifications to corlib_native_System_Number.cpp add special handling for negative zero cases, ensuring proper formatting output for ToString("N0") and ToString("F0") scenarios. These changes work together to resolve the incorrect formatted string output that was the primary complaint in the linked issue.
Out of Scope Changes Check ✅ Passed All code changes in the pull request are directly related to fixing the identified bug in ToString("N0") and ToString("F0") formatting. The rounding logic updates in nanoprintf.c address the core issue of incorrect rounding when values should round up, and the precision handling and rollover adjustments are necessary to fix this behavior. The changes to corlib_native_System_Number.cpp to handle negative zero are supporting changes needed to ensure correct formatted output. No extraneous or unrelated modifications are present in the changeset.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Fix edge cases in format F and N with precision 0 and 1" accurately describes the main objectives of the changeset. The PR specifically addresses rounding issues in the F and N format implementations, with the primary focus on fixing incorrect output when precision is 0 (e.g., ToString("F0") and ToString("N0")). The title is specific and clear about which format types are affected and which precision levels are involved, making it easy for teammates to understand the main change when scanning the commit history. The title directly corresponds to the linked issue #1688 that describes the rounding bug for values like 9.8999 formatting incorrectly.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@josesimoes josesimoes changed the title Reworked rounding logic in nanoprintf Fix edge cases in format F and N with precision 0 and 1 Oct 31, 2025
@josesimoes josesimoes merged commit 5ee2558 into nanoframework:main Oct 31, 2025
27 checks passed
@josesimoes josesimoes deleted the fix-nanoprintf branch October 31, 2025 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: Common libs Everything related with common libraries hacktoberfest-accepted Type: bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix tostring handling code to deal with ToString("N0") with doubles and floats

2 participants