-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
float.__format__() handles trailing zeros inconsistently in “general” format #84957
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
Comments
According to https://docs.python.org/3/library/string.html#format-specification-mini-language, “insignificant trailing zeros are removed from the significand” when 'g' is specified. I encountered a situation in which a trailing zero is not removed: $ python3
Python 3.7.7 (default, Mar 10 2020, 15:43:03)
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> '{0:.3g}'.format(1504)
'1.5e+03'
>>> '{0:.3g}'.format(1505)
'1.50e+03'
>>> '{0:.3g}'.format(1506)
'1.51e+03' Is this behaviour intentional? If so, why is the trailing zero in 1.50 considered significant for 1505 but insignificant for 1504? |
FWIW, which is probably not much with ".g" formatting, this is how Decimal behaves: >>> from decimal import Decimal as D
>>> format(D(1504), '.3g')
'1.50e+3'
>>> format(D(1505), '.3g')
'1.50e+3'
>>> format(D(1506), '.3g')
'1.51e+3'
>>> format(D(1504.0), '.3g')
'1.50e+3'
>>> format(D(1505.0), '.3g')
'1.50e+3'
>>> format(D(1506.0), '.3g')
'1.51e+3'
>>> format(D("1504.0"), '.3g')
'1.50e+3'
>>> format(D("1505.0"), '.3g')
'1.50e+3'
>>> format(D("1506.0"), '.3g')
'1.51e+3' |
Very interesting. Agreed that this looks like a bug. It affects old-style formatting, too: >>> "%.3g" % 1503
'1.5e+03'
>>> "%.3g" % 1504
'1.5e+03'
>>> "%.3g" % 1505
'1.50e+03' |
This appears to go all the way down to _Py_dg_dtoa, which in mode 3 is supposed to suppress trailing zeros. I'll dig in and see if I can find a fix. (Assigning to me so that I don't forget it, but I also don't want to block anyone else - if anyone else feels like working on this, please do go ahead.) |
For completeness, here's the output using just format, which I prefer over str.format because there's less going on: it removes all of the str.format machinery and basically directly calls obj.__format__. >>> format(1504, '.3g')
'1.5e+03'
>>> format(1505, '.3g')
'1.50e+03'
>>> format(1506, '.3g')
'1.51e+03' |
Created a PR with a tentative fix. It still needs regression tests; working on those. |
The PR is ready for review. |
I'm wondering how far back the fix should be backported. Clearly it should go into the 3.9 branch as well as master, but it feels like the sort of fix where the behaviour change resulting from the fix is as likely to break code as the bug itself. |
I think I'd just do 3.9 and master. It does seem subtle for a minor release, when people are less likely to be looking at the release notes. |
+1 for 3.9 and later. |
Fixed in master and 3.9; not backporting to 3.8 or 3.7, as discussed. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: