def round3(number, ndigits=None):
"""
Implementation of Python 3 built-in round() function.
Rounds a number to a given precision in decimal digits (default
0 digits). This returns an int when ndigits is omitted or is None,
otherwise the same type as the number.
Values are rounded to the closest multiple of 10 to the power minus
ndigits; if two multiples are equally close, rounding is done toward
the even choice (aka "Banker's Rounding"). For example, both round(0.5)
and round(-0.5) are 0, and round(1.5) is 2.
ndigits may be negative.
See Python 3 documentation:
https://docs.python.org/3/library/functions.html?highlight=round#round
Derived from python-future:
https://github.com/PythonCharmers/python-future/blob/master/src/future/builtins/newround.py
"""
if ndigits is None:
ndigits = 0
# return an int when called with one argument
totype = int
# shortcut if already an integer, or a float with no decimal digits
inumber = totype(number)
if inumber == number:
return inumber
else:
# return the same type as the number, when called with two arguments
totype = type(number)
m = number * (10 ** ndigits)
# if number is half-way between two multiples, and the mutliple that is
# closer to zero is even, we use the (slow) pure-Python implementation
if isclose(m % 1, .5) and int(m) % 2 == 0:
if ndigits < 0:
exponent = 10 ** (-ndigits)
quotient, remainder = divmod(number, exponent)
half = exponent//2
if remainder > half or (remainder == half and quotient % 2 != 0):
quotient += 1
d = quotient * exponent
else:
exponent = _decimal.Decimal('10') ** (-ndigits) if ndigits != 0 else 1
d = _decimal.Decimal.from_float(number).quantize(
exponent, rounding=_decimal.ROUND_HALF_EVEN)
else:
# else we use the built-in round() as it produces the same results
d = round2(number, ndigits)
return totype(d)
评论列表
文章目录