Fix directional rounding (ROUND_CEILING/ROUND_FLOOR) for negative numbers#1286
Open
vineethsaivs wants to merge 1 commit into
Open
Fix directional rounding (ROUND_CEILING/ROUND_FLOOR) for negative numbers#1286vineethsaivs wants to merge 1 commit into
vineethsaivs wants to merge 1 commit into
Conversation
ROUND_CEILING and ROUND_FLOOR produced the wrong result when formatting a negative number. NumberPattern.apply() strips the sign before any rounding (it formats the magnitude and renders the sign via the pattern affixes), so the directional rounding modes rounded the magnitude and ended up rounding toward the wrong infinity. For example, with ROUND_CEILING, format_decimal of -100.75 returned -101 instead of -100 (ceil(-100.75) == -100). Round using the value's original sign in both rounding sites, _quantize_value and _format_significant, then format the magnitude. The sign-symmetric modes (ROUND_HALF_*, ROUND_UP, ROUND_DOWN, ROUND_05UP) and all positive-number formatting are unaffected. Fixes python-babel#1096.
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.
Overview
Fixes #1096.
ROUND_CEILINGandROUND_FLOORproduced the wrong result when formatting anegative number:
Root cause
NumberPattern.apply()separates the sign from the value up front(
value = abs(value).normalize()), formats the magnitude, and renders the signseparately through the pattern's affixes. Because the sign was already gone by
the time rounding happened, the directional rounding modes (
ROUND_CEILING,ROUND_FLOOR) were applied to the magnitude and therefore rounded toward thewrong infinity for negative numbers. Effectively
ROUND_CEILINGbehaved likeROUND_UPandROUND_FLOORlikeROUND_DOWNfor negatives.This affected every rounding site that operates on the magnitude:
_quantize_value(plain and fractional patterns, e.g.#and#,##0.00, plusthe scientific-notation mantissa) and
_format_significant(significant-digitspatterns such as
@@).Fix
Round using the value's original sign in both sites, then format the magnitude
(the sign is still rendered via the affixes, so output formatting is otherwise
unchanged). The sign-symmetric modes (
ROUND_HALF_*,ROUND_UP,ROUND_DOWN,ROUND_05UP) and all positive-number formatting are unaffected; verifiedagainst
decimal.Decimal.quantizeon the signed value across every roundingmode.
Tests
Added
test_format_decimal_negative_directional_rounding(parametrized over therounding modes) and
test_format_decimal_negative_directional_rounding_significant.Both fail on
masterfor the directional modes and pass with this change. Thefull
tests/test_numbers.pysuite passes (137 tests).