-
-
Notifications
You must be signed in to change notification settings - Fork 80
Fix plural form for intword and improve performance
#273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,8 @@ | |||||
|
|
||||||
| from __future__ import annotations | ||||||
|
|
||||||
| import bisect | ||||||
|
|
||||||
| from .i18n import _gettext as _ | ||||||
| from .i18n import _ngettext, decimal_separator, thousands_separator | ||||||
| from .i18n import _ngettext_noop as NS_ | ||||||
|
|
@@ -194,8 +196,8 @@ def intword(value: NumberOrString, format: str = "%.1f") -> str: | |||||
| """Converts a large integer to a friendly text representation. | ||||||
|
|
||||||
| Works best for numbers over 1 million. For example, 1_000_000 becomes "1.0 million", | ||||||
| 1200000 becomes "1.2 million" and "1_200_000_000" becomes "1.2 billion". Supports up | ||||||
| to decillion (33 digits) and googol (100 digits). | ||||||
| 1_200_000 becomes "1.2 million" and "1_200_000_000" becomes "1.2 billion". Supports | ||||||
| up to decillion (33 digits) and googol (100 digits). | ||||||
|
|
||||||
| Examples: | ||||||
| ```pycon | ||||||
|
|
@@ -241,29 +243,26 @@ def intword(value: NumberOrString, format: str = "%.1f") -> str: | |||||
| negative_prefix = "" | ||||||
|
|
||||||
| if value < powers[0]: | ||||||
| return negative_prefix + str(value) | ||||||
|
|
||||||
| for ordinal_, power in enumerate(powers[1:], 1): | ||||||
| if value < power: | ||||||
| chopped = value / float(powers[ordinal_ - 1]) | ||||||
| powers_difference = powers[ordinal_] / powers[ordinal_ - 1] | ||||||
| if float(format % chopped) == powers_difference: | ||||||
| chopped = value / float(powers[ordinal_]) | ||||||
| singular, plural = human_powers[ordinal_] | ||||||
| return ( | ||||||
| negative_prefix | ||||||
| + " ".join( | ||||||
| [format, _ngettext(singular, plural, math.ceil(chopped))] | ||||||
| ) | ||||||
| ) % chopped | ||||||
|
|
||||||
| singular, plural = human_powers[ordinal_ - 1] | ||||||
| return ( | ||||||
| negative_prefix | ||||||
| + " ".join([format, _ngettext(singular, plural, math.ceil(chopped))]) | ||||||
| ) % chopped | ||||||
|
|
||||||
| return negative_prefix + str(value) | ||||||
| return f"{negative_prefix}{value}" | ||||||
|
|
||||||
| ordinal = bisect.bisect_right(powers, value) | ||||||
| largest_ordinal = ordinal == len(powers) | ||||||
|
|
||||||
| # Consider the biggest power of 10 that is smaller than value | ||||||
| ordinal -= 1 | ||||||
| power = powers[ordinal] | ||||||
| chopped = value / power | ||||||
| rounded_value = float(format % chopped) | ||||||
|
|
||||||
| if not largest_ordinal and rounded_value * power == powers[ordinal + 1]: | ||||||
| # After rounding, we end up just at the next power | ||||||
| ordinal += 1 | ||||||
| power = powers[ordinal] | ||||||
| rounded_value = 1.0 | ||||||
|
|
||||||
| singular, plural = human_powers[ordinal] | ||||||
| unit = _ngettext(singular, plural, math.ceil(rounded_value)) | ||||||
| return f"{negative_prefix}{rounded_value} {unit}" | ||||||
|
||||||
| return f"{negative_prefix}{rounded_value} {unit}" | |
| return f"{negative_prefix}{format % rounded_value} {unit}" |
And we could add some test cases like this to the main test_intword():
(["1234567", "%.0f"], "1 million"),
(["1234567", "%.1f"], "1.2 million"),
(["1234567", "%.2f"], "1.23 million"),
(["1234567", "%.3f"], "1.235 million"),
(["999500", "%.0f"], "1 million"),
(["999499", "%.0f"], "999 thousand"),There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good catch! I added what you suggested. Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't used:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a lot of refactoring. Thanks for noticing that this was still here. You're 100% right. It's not even needed anymore. :)