fix(number_format): round decimal display values half away from zero like Excel#345
Merged
MathNya merged 2 commits intoJul 22, 2026
Conversation
Decimal display values were truncated toward zero (107310.6 with #,##0 printed 107,310) and short fractions were multiplied instead of padded (39.1 with 0.00 printed 39.100). Percentages routed ties through binary doubles (1.065 with 0% printed 106% instead of 107%). Round the decimal string directly: half away from zero at the format's fractional width, zero-padding short fractions, with string-based thousands grouping, and shift percentages by moving the decimal point. Signed-off-by: Yonghye Kwon <developer.0hye@gmail.com>
Contributor
|
@developer0hye would you be able to address the two failing tests? The fix doesn't look like it should be too hard. One looks like just to run cargo fmt with nightly rust and the other is just to fix a format string. If you're getting trouble let me and I can give it a try, shouldn't be too hard. |
…rmat-args - Inline format args in round_decimal_string (clippy::uninlined-format-args) - Apply nightly cargo fmt to number_formater.rs and percentage_formater.rs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Author
|
@c-git Thanks for the pointers — both were exactly as you described. Fixed in 865316a:
All checks are green now (build stable/beta/nightly/1.88.0 + formatting). No changes to the actual rounding logic. Thanks for the review! |
Contributor
|
I didn't get a chance to actually understand the code. I just noticed that those were easy fixes. |
Owner
|
@developer0hye |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
get_formatted_value()disagrees with Excel's rendering for three common cases:107310.6with#,##0returns107,310; Excel shows107,311.format_straight_numeric_valuereturned the integer block verbatim whenever the format had no decimals.39.1with0.00returns39.100: the right-side digits were parsed as an integer and multiplied by10^width(1 × 100 = 100) rather than padded to10.1.065with0%returns106%; Excel shows107%.1.065 × 100in binary doubles is106.4999…, so anything that multiplies first loses the tie. Excel rounds the decimal display value.Fix
Round the decimal string directly instead of routing values back through binary floats:
round_decimal_stringrounds a plain decimal string (as produced byf64::to_string, i.e. shortest round-trip) half away from zero at the format's fractional width, zero-padding short fractions, with digit-carry propagation for999.95-style rollovers. Exponent-notation input falls back to float formatting.group_thousandsinserts comma separators into the integer part by string, so grouping survives rounding carries (999,999.5with#,##0→1,000,000) and values beyond integer range keep their digits.format_as_percentagenow multiplies by shifting the decimal point in the string (1.065→106.5) before rounding, which preserves decimal ties exactly.Testing
number_formater.rscovering half-away rounding (positive/negative), zero-padding, excess-decimal rounding, currency prefixes, and thousands grouping through rounding carries, plus tie-rounding tests inpercentage_formater.rscargo test— full suite green (94 + 112 + 79 + 4 tests)🤖 Generated with Claude Code