Skip to content

Fix fractional() emitting degenerate output when the fraction rounds to a whole - #354

Open
semx wants to merge 1 commit into
python-humanize:mainfrom
semx:fix-fractional-whole-rounding
Open

Fix fractional() emitting degenerate output when the fraction rounds to a whole#354
semx wants to merge 1 commit into
python-humanize:mainfrom
semx:fix-fractional-whole-rounding

Conversation

@semx

@semx semx commented Jul 20, 2026

Copy link
Copy Markdown

Noticed while probing edge cases: fractional() emits degenerate output when the fractional part rounds to a whole number.

>>> import humanize
>>> humanize.fractional(2.9999999)
'2 1/1'        # expected '3'
>>> humanize.fractional(0.9999999)
'1/1'          # expected '1'
>>> humanize.fractional(0)
'0/1'          # expected '0'

Cause

After frac = Fraction(number - whole_number).limit_denominator(1000), when the fractional part reduces to a whole number the denominator is 1 (numerator ∈ {-1, 0, 1}). The existing special case only handled numerator == 0 (a plain integer input like 1.0), so:

  • numerator == 1 (the fraction rounded up to 1/1) fell through to the mixed-fraction branch → "2 1/1";
  • fractional(0) produced "0/1".

Changes proposed in this pull request:

  • Fold any whole-valued fractional part (denominator == 1) into the integer part, so the result reads as a normal integer.
  • Add regression tests for 0, 0.0, 2.9999999, 0.9999999, -2.9999999.

All existing tests pass (705 passed); ruff and black clean.

…to a whole

When limit_denominator(1000) reduces the fractional part to a whole number
(denominator == 1), fold it into the integer part instead of printing a
degenerate "N/1". For example fractional(2.9999999) returned "2 1/1"
instead of "3", fractional(0.9999999) returned "1/1" instead of "1",
and fractional(0) returned "0/1" instead of "0".
@semx

semx commented Aug 5, 2026

Copy link
Copy Markdown
Author

Gentle ping. This fixes fractional() emitting degenerate output (a whole number rendered as "2 1/1") when the fraction rounds to a whole; it now returns the plain integer, with tests for the boundary cases. docs and pre-commit.ci are green. Let me know if any change would help it land. 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.

1 participant