second commit
This commit is contained in:
105
env/lib/python3.11/site-packages/future/builtins/newround.py
vendored
Normal file
105
env/lib/python3.11/site-packages/future/builtins/newround.py
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
"""
|
||||
``python-future``: pure Python implementation of Python 3 round().
|
||||
"""
|
||||
|
||||
from __future__ import division
|
||||
from future.utils import PYPY, PY26, bind_method
|
||||
|
||||
# Use the decimal module for simplicity of implementation (and
|
||||
# hopefully correctness).
|
||||
from decimal import Decimal, ROUND_HALF_EVEN
|
||||
|
||||
|
||||
def newround(number, ndigits=None):
|
||||
"""
|
||||
See Python 3 documentation: uses Banker's Rounding.
|
||||
|
||||
Delegates to the __round__ method if for some reason this exists.
|
||||
|
||||
If not, rounds a number to a given precision in decimal digits (default
|
||||
0 digits). This returns an int when called with one argument,
|
||||
otherwise the same type as the number. ndigits may be negative.
|
||||
|
||||
See the test_round method in future/tests/test_builtins.py for
|
||||
examples.
|
||||
"""
|
||||
return_int = False
|
||||
if ndigits is None:
|
||||
return_int = True
|
||||
ndigits = 0
|
||||
if hasattr(number, '__round__'):
|
||||
return number.__round__(ndigits)
|
||||
|
||||
exponent = Decimal('10') ** (-ndigits)
|
||||
|
||||
# Work around issue #24: round() breaks on PyPy with NumPy's types
|
||||
# Also breaks on CPython with NumPy's specialized int types like uint64
|
||||
if 'numpy' in repr(type(number)):
|
||||
number = float(number)
|
||||
|
||||
if isinstance(number, Decimal):
|
||||
d = number
|
||||
else:
|
||||
if not PY26:
|
||||
d = Decimal.from_float(number)
|
||||
else:
|
||||
d = from_float_26(number)
|
||||
|
||||
if ndigits < 0:
|
||||
result = newround(d / exponent) * exponent
|
||||
else:
|
||||
result = d.quantize(exponent, rounding=ROUND_HALF_EVEN)
|
||||
|
||||
if return_int:
|
||||
return int(result)
|
||||
else:
|
||||
return float(result)
|
||||
|
||||
|
||||
### From Python 2.7's decimal.py. Only needed to support Py2.6:
|
||||
|
||||
def from_float_26(f):
|
||||
"""Converts a float to a decimal number, exactly.
|
||||
|
||||
Note that Decimal.from_float(0.1) is not the same as Decimal('0.1').
|
||||
Since 0.1 is not exactly representable in binary floating point, the
|
||||
value is stored as the nearest representable value which is
|
||||
0x1.999999999999ap-4. The exact equivalent of the value in decimal
|
||||
is 0.1000000000000000055511151231257827021181583404541015625.
|
||||
|
||||
>>> Decimal.from_float(0.1)
|
||||
Decimal('0.1000000000000000055511151231257827021181583404541015625')
|
||||
>>> Decimal.from_float(float('nan'))
|
||||
Decimal('NaN')
|
||||
>>> Decimal.from_float(float('inf'))
|
||||
Decimal('Infinity')
|
||||
>>> Decimal.from_float(-float('inf'))
|
||||
Decimal('-Infinity')
|
||||
>>> Decimal.from_float(-0.0)
|
||||
Decimal('-0')
|
||||
|
||||
"""
|
||||
import math as _math
|
||||
from decimal import _dec_from_triple # only available on Py2.6 and Py2.7 (not 3.3)
|
||||
|
||||
if isinstance(f, (int, long)): # handle integer inputs
|
||||
return Decimal(f)
|
||||
if _math.isinf(f) or _math.isnan(f): # raises TypeError if not a float
|
||||
return Decimal(repr(f))
|
||||
if _math.copysign(1.0, f) == 1.0:
|
||||
sign = 0
|
||||
else:
|
||||
sign = 1
|
||||
n, d = abs(f).as_integer_ratio()
|
||||
# int.bit_length() method doesn't exist on Py2.6:
|
||||
def bit_length(d):
|
||||
if d != 0:
|
||||
return len(bin(abs(d))) - 2
|
||||
else:
|
||||
return 0
|
||||
k = bit_length(d) - 1
|
||||
result = _dec_from_triple(sign, str(n*5**k), -k)
|
||||
return result
|
||||
|
||||
|
||||
__all__ = ['newround']
|
Reference in New Issue
Block a user