Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Exceptions from round implementation #322

Copy link
Copy link
@mdickinson

Description

@mdickinson
Issue body actions

[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.)

Reactions are currently unavailable

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.