Skip to content
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

gh-99880: document rounding mode for new-style formatting #121481

Merged
merged 3 commits into from
Nov 2, 2024

Conversation

skirpichev
Copy link
Member

@skirpichev skirpichev commented Jul 8, 2024

The CPython uses _Py_dg_dtoa(), which does rounding to nearest with half to even tie-breaking rule.

If that functions is unavailable, PyOS_double_to_string() fallbacks to system snprintf(). Since CPython 3.12, build requirements include C11 compiler and support for IEEE 754 floating-point numbers. C17 says here (p 230, "Recommended practice"): "For e, E, f, F, g, and G conversions, if the number of significant decimal digits is at most DECIMAL_DIG, then the result should be correctly rounded."


📚 Documentation preview 📚: https://cpython-previews--121481.org.readthedocs.build/

The CPython uses _Py_dg_dtoa(), which does rounding to nearest with half
to even tie-breaking rule.

If that functions is unavailable, PyOS_double_to_string() fallbacks to
system snprintf().  Since CPython 3.12, build requirements include C11
compiler *and* support for IEEE 754 floating point numbers (Annex F).
This means that FE_TONEAREST macro is available and, per default,
printf-like functions should use same rounding mode as _Py_dg_dtoa().
@jowagner
Copy link

jowagner commented Jul 9, 2024

My opinion (not a core developer):

  • The word "correctly" doesn't add anything useful here as correctness is subjective, i.e. what is the correct way of rounding to one person may be wrong to another. Suggest removing this word.
  • Not clear what kind of vagueness is expressed with "it should round" here. Suggestion: "it will, on common platforms, round".
  • Many readers may not understand what least significant bits have to do with decimals. Suggestion: "[...] toward the value with an even last digit (0, 2, 4, 6 or 8) in its representation." (For midway values, there are always two nearest values and one is always odd and the other even, so there is exactly one even value. Note also that "even" and "odd" are not properties of numbers alone but only of numbers with a selected format, e.g. 3 is odd for .0f but even for .1f.)

Copy link
Member Author

@skirpichev skirpichev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jowagner, thanks for review.

The word "correctly" doesn't add anything useful here as correctness is subjective

The meaning in this context actually is not subjective at all. From § 3.9 of the C11 standard: correctly rounded result - representation in the result format that is nearest in value, subject to the current rounding mode, to what the result would be given unlimited range and precision.

Maybe it worth to add something like above definition to the glossary? It's used a lot e.g. in the decimal module.

Suggestion: "it will, on common platforms, round".

+1

Many readers may not understand what least significant bits have to do with decimals.

Well, it's a bit not a digit;) Hardly we should everywhere emphasize that floats are binary floating point numbers. I would prefer if more detailed description (in depth, with examples and with a warning!) will be consolidated in round() docs. There is a link.

Suggestion: "[...] toward the value with an even last digit (0, 2, 4, 6 or 8) in its representation."

I doubt it's a correct description. Consider this example:

>>> round(2.675, 2)
2.67
>>> from decimal import Decimal, getcontext
>>> getcontext().rounding
'ROUND_HALF_EVEN'
>>> round(Decimal('2.675'), 2)
Decimal('2.68')

Doc/library/string.rst Outdated Show resolved Hide resolved
Doc/library/string.rst Outdated Show resolved Hide resolved
Co-authored-by: Bénédikt Tran <[email protected]>
@skirpichev skirpichev added needs backport to 3.12 bug and security fixes needs backport to 3.13 bugs and security fixes labels Oct 9, 2024
Copy link
Contributor

@willingc willingc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me @skirpichev. There is a merge conflict that needs resolution. Thanks.

@skirpichev
Copy link
Member Author

Thanks, fixed.

Copy link
Contributor

@willingc willingc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @skirpichev.

@willingc willingc merged commit 7d7d56d into python:main Nov 2, 2024
29 checks passed
@miss-islington-app
Copy link

Thanks @skirpichev for the PR, and @willingc for merging it 🌮🎉.. I'm working now to backport this PR to: 3.12, 3.13.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Nov 2, 2024
…onGH-121481)

* pythongh-99880: document rounding mode for new-style formatting

The CPython uses _Py_dg_dtoa(), which does rounding to nearest with half
to even tie-breaking rule.

If that functions is unavailable, PyOS_double_to_string() fallbacks to
system snprintf().  Since CPython 3.12, build requirements include C11
compiler *and* support for IEEE 754 floating point numbers (Annex F).
This means that FE_TONEAREST macro is available and, per default,
printf-like functions should use same rounding mode as _Py_dg_dtoa().

* Update Doc/library/string.rst

Co-authored-by: Bénédikt Tran <[email protected]>

---------

(cherry picked from commit 7d7d56d)

Co-authored-by: Sergey B Kirpichev <[email protected]>
Co-authored-by: Bénédikt Tran <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Nov 2, 2024
…onGH-121481)

* pythongh-99880: document rounding mode for new-style formatting

The CPython uses _Py_dg_dtoa(), which does rounding to nearest with half
to even tie-breaking rule.

If that functions is unavailable, PyOS_double_to_string() fallbacks to
system snprintf().  Since CPython 3.12, build requirements include C11
compiler *and* support for IEEE 754 floating point numbers (Annex F).
This means that FE_TONEAREST macro is available and, per default,
printf-like functions should use same rounding mode as _Py_dg_dtoa().

* Update Doc/library/string.rst

Co-authored-by: Bénédikt Tran <[email protected]>

---------

(cherry picked from commit 7d7d56d)

Co-authored-by: Sergey B Kirpichev <[email protected]>
Co-authored-by: Bénédikt Tran <[email protected]>
@bedevere-app
Copy link

bedevere-app bot commented Nov 2, 2024

GH-126334 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.13 bugs and security fixes label Nov 2, 2024
@bedevere-app
Copy link

bedevere-app bot commented Nov 2, 2024

GH-126335 is a backport of this pull request to the 3.12 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.12 bug and security fixes label Nov 2, 2024
@skirpichev skirpichev deleted the format-rounding-docs-99880 branch November 2, 2024 17:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation in the Doc dir skip news
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants