Skip to content

Fix format_size() rounding rollover at unit boundaries#82

Open
patchwright wants to merge 1 commit into
xolox:masterfrom
patchwright:bugfix/format-size-rounding-rollover
Open

Fix format_size() rounding rollover at unit boundaries#82
patchwright wants to merge 1 commit into
xolox:masterfrom
patchwright:bugfix/format-size-rounding-rollover

Conversation

@patchwright

Copy link
Copy Markdown

Problem

format_size() picks the unit by comparing the raw byte count to each divider, then rounds the mantissa with round_number() afterward. When rounding pushes the mantissa up to the base, the already-chosen unit is left stale:

>>> from humanfriendly import format_size
>>> format_size(999999)
'1000 KB'      # expected '1 MB'
>>> format_size(999999999)
'1000 MB'      # expected '1 GB'
>>> format_size(1024 ** 2 - 1, binary=True)
'1024 KiB'     # expected '1 MiB'

999999 bytes is 999.999 KB; '%.2f' rounds that to 1000, but the unit was already fixed at KB, so the output reads 1000 KB instead of 1 MB. The same happens at every decimal and binary boundary.

Fix

After rounding, if the mantissa has reached the base (1000 decimal / 1024 binary) and a larger unit is available, carry into that next unit and re-render. Values already at the largest unit (YB/YiB) are unaffected, as are all values that don't round across a boundary.

Tests

Added regression assertions to test_format_size covering the decimal and binary boundaries. They fail on the current code and pass with this change; every existing assertion is unchanged.

format_size() chooses the unit by comparing the raw byte count to each
divider, then rounds the mantissa with round_number() afterward. When the
mantissa rounds up to the base (e.g. 999999 bytes is 999.999 KB, which rounds
to '1000 KB'), the already-chosen unit is left stale:

    >>> format_size(999999)
    '1000 KB'              # expected '1 MB'
    >>> format_size(999999999)
    '1000 MB'              # expected '1 GB'
    >>> format_size(1024 ** 2 - 1, binary=True)
    '1024 KiB'            # expected '1 MiB'

Fix: after rounding, if the mantissa has reached the base and a larger unit
is available, carry into that next unit and re-render. Added regression cases
to test_format_size (they fail before this change, pass after); all existing
assertions are unchanged.
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