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

Exceptions from round implementation #322

Open
mdickinson opened this issue Jan 20, 2018 · 0 comments
Open

Exceptions from round implementation #322

mdickinson opened this issue Jan 20, 2018 · 0 comments

Comments

@mdickinson
Copy link

mdickinson commented Jan 20, 2018

[Prompted by this StackOverflow question]

There are a couple of issues with the current implementation of round from builtins:

  • it doesn't support negative second argument:
>>> from builtins import round
>>> round(314, -2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/future/builtins/newround.py", line 33, in newround
    raise NotImplementedError('negative ndigits not supported yet')
NotImplementedError: negative ndigits not supported yet
  • it can raise decimal.InvalidOperation:
>>> round(1e50, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/future/builtins/newround.py", line 43, in newround
    rounding=ROUND_HALF_EVEN)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/decimal.py", line 2468, in quantize
    'quantize result has too many digits for current context')
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/decimal.py", line 3872, in _raise_error
    raise error(explanation)
decimal.InvalidOperation: quantize result has too many digits for current context

The first restriction seems unnecessary. The second can be overcome by using a dedicated decimal context with sufficient precision. For rounding a float x to n decimal places (with n possibly negative), I'd suggest something like the following:

from decimal import Context, Decimal
c = Context(prec=800)  # sufficient precision that the `quantize` result is representable
quantum = Decimal("1e{}".format(-n))  # should work for both n positive and negative
rounded = float(c.quantize(Decimal(x), quantum))

(The bound of 800 here is a bit crude. The maximum number of significant digits needed to represent any IEEE 754 binary64 float exactly in decimal is 767.)

kayneb added a commit to kayneb/python-future that referenced this issue Dec 19, 2019
…nally, fixing a bug so that it handles passing in Decimal properly
jmadler added a commit that referenced this issue Feb 5, 2020
…to-round

#322 Add support for negative ndigits in round; additionally, fixing …
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