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

Differences with round behavior compared to CPython #517

Open
pekkaklarck opened this issue Sep 12, 2018 · 1 comment
Open

Differences with round behavior compared to CPython #517

pekkaklarck opened this issue Sep 12, 2018 · 1 comment

Comments

@pekkaklarck
Copy link

Using Python 2.7:

>>> round(1.15, 1)
1.1
>>> round(2.675, 2)
2.67

The reason that these numbers are rounded down, not up like Python 2 generally should do, is that they cannot be represented exactly and, for example, 1.15 is actually '1.149999999999999911182158029987476766109466552734375 which is closer to 1.1 than 1.2. This issue with representing numbers is due to how floats are represented internally in binary format and affects IronPython exactly like it affects CPython. With IronPython round works differently, though. Using IronPython 2.7.9rc1:

>>> round(1.15, 1)
1.2
>>> round(2.675, 2)
2.6800000000000002

Not sure could this issue cause any real problems with real code. The latter example above is, however, directly against IronPython documentation for round (which seems to be directly copied from CPython).

Notice also that it's not only exactly these exact numbers that are surprisingly rounded up with IronPython:

>>> round(1.149999999999999, 1)
1.1000000000000001
>>> round(1.1499999999999999, 1)
1.2
@slozier
Copy link
Contributor

slozier commented Sep 12, 2018

The underlying cause for the rounding issue is the rounding algorithm which essentially does round(1.1499999999999999 * 10) / 10. Since 1.1499999999999999 * 10 == 11.5 (and 11.5 is exactly representable), the midpoint rounding makes it go up to 12.

It looks like CPython actually uses double to string (via dtoa) conversion to properly do its rounding. There is fallback code in there which is used when dtoa isn't available which does the exact same rounding as we have.

Probably not worth spending any more time on this issue since as mentioned it probably doesn't cause any issues with real code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants