This issue tracker has been migrated to GitHub ,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2015年06月07日 10:58 by priska, last changed 2022年04月11日 14:58 by admin. This issue is now closed.
| Messages (7) | |||
|---|---|---|---|
| msg244951 - (view) | Author: priska (priska) | Date: 2015年06月07日 10:58 | |
The behavior of the round() function has changed between Python 2.x and Python3.x. From the release notes of Python 3.0: "The round() function rounding strategy and return type have changed. Exact halfway cases are now rounded to the nearest even result instead of away from zero. (For example, round(2.5) now returns 2 rather than 3.) round(x[, n]) now delegates to x.__round__([n]) instead of always returning a float. It generally returns an integer when called with a single argument and a value of the same type as x when called with two arguments." 2to3 conversion does not take this into account and thereby changes code behavior. Suggested translations: round(n) -> float(math.floor(n + math.copysign(0.5, n))) or round(n) -> float(math.trunc(n + math.copysign(0.5, n))) |
|||
| msg244952 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2015年06月07日 11:51 | |
This is a bit tricky. The first expression you suggest doesn't work at all for negative numbers (e.g., producing `-3.0` for `round(-1.8)`). The second expression *mostly* works as you want, but not entirely. Some examples: >>> def f(n): return float(math.trunc(n + math.copysign(0.5, n))) ... >>> x = 0.5 - 2**-54 >>> x 0.49999999999999994 >>> f(x) # should be 0.0 1.0 >>> x = 5e15 + 3.0 >>> x 5000000000000003.0 >>> f(x) # should be x again 5000000000000004.0 And neither of these addresses the two-argument case of `round`. It may be better to simply flag this as something that 2to3 can't handle, and that needs a manual check. |
|||
| msg244953 - (view) | Author: priska (priska) | Date: 2015年06月07日 12:39 | |
Yes, those quick suggestions weren't thoroughly tested at all and turned out to be too short-sighted – thanks for checking, but are you saying the old behavior cannot be emulated or that it is not desirable to to so? |
|||
| msg244970 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2015年06月07日 19:58 | |
The old behaviour certainly can be emulated, but doing that correctly would require 4 or 5 lines of code. I don't know enough about 2to3 to know whether it can handle that sort of translation, but even if it can, I'd guess that in a good proportion of cases the loss in readability (and possibly also in performance) wouldn't be worth it, and in many cases the difference in behaviour may not matter either. Given all that, I think it's probably better left as a judgement call on the part of the person doing the 2-to-3 porting. Here's a translation that's immune from the two issues I pointed out. def round_ties_away_from_zero(x): n = round(x) if abs(x - n) == 0.5: # x - n is exact; no rounding error return x + copysign(0.5, x) else: return float(n) |
|||
| msg245268 - (view) | Author: Terry J. Reedy (terry.reedy) * (Python committer) | Date: 2015年06月12日 19:22 | |
The fix would be to add a 'round' function at the top of a module, after the imports. This is more the provenance of 2 & 3 compatibility modules, such as 6, which might have both round2 and round3 functions. |
|||
| msg245296 - (view) | Author: Tal Einat (taleinat) * (Python committer) | Date: 2015年06月13日 06:45 | |
See the existing issue and discussion about this on the six library's issue tracker (opened nearly a year ago): https://bitbucket.org/gutworth/six/issue/94/introduce-sixround |
|||
| msg377234 - (view) | Author: Irit Katriel (iritkatriel) * (Python committer) | Date: 2020年09月20日 22:04 | |
Looks like this issue can be closed as rejected. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:58:17 | admin | set | github: 68591 |
| 2020年09月21日 06:31:40 | serhiy.storchaka | set | status: open -> closed resolution: wont fix stage: resolved |
| 2020年09月20日 22:04:01 | iritkatriel | set | nosy:
+ iritkatriel messages: + msg377234 |
| 2018年06月11日 14:18:30 | taleinat | set | nosy:
- taleinat |
| 2015年06月13日 06:45:22 | taleinat | set | nosy:
+ taleinat messages: + msg245296 |
| 2015年06月12日 19:22:20 | terry.reedy | set | nosy:
+ terry.reedy messages: + msg245268 |
| 2015年06月08日 00:12:37 | ned.deily | set | nosy:
+ benjamin.peterson |
| 2015年06月07日 19:58:34 | mark.dickinson | set | messages: + msg244970 |
| 2015年06月07日 12:39:49 | priska | set | messages: + msg244953 |
| 2015年06月07日 11:51:34 | mark.dickinson | set | nosy:
+ mark.dickinson messages: + msg244952 |
| 2015年06月07日 10:58:41 | priska | create | |