Always round off
decimal
from decimal import Decimal, ROUND_HALF_UP
def round(number, ndigits=None):
"""Always round off"""
exp = Decimal('1.{}'.format(ndigits * '0')) if ndigits else Decimal('1')
return type(number)(Decimal(number).quantize(exp, ROUND_HALF_UP))
print(round(4.115, 2), type(round(4.115, 2)))
print(round(4.116, 2), type(round(4.116, 2)))
print(round(4.125, 2), type(round(4.125, 2)))
print(round(4.126, 2), type(round(4.126, 2)))
print(round(2.5), type(round(2.5)))
print(round(3.5), type(round(3.5)))
print(round(5), type(round(5)))
print(round(6), type(round(6)))
# 4.12 <class 'float'>
# 4.12 <class 'float'>
# 4.13 <class 'float'>
# 4.13 <class 'float'>
# 3.0 <class 'float'>
# 4.0 <class 'float'>
# 5 <class 'int'>
# 6 <class 'int'>
math
import math
def round(number, ndigits=0):
"""Always round off"""
exp = number * 10 ** ndigits
if abs(exp) - abs(math.floor(exp)) < 0.5:
return type(number)(math.floor(exp) / 10 ** ndigits)
return type(number)(math.ceil(exp) / 10 ** ndigits)
print(round(4.115, 2), type(round(4.115, 2)))
print(round(4.116, 2), type(round(4.116, 2)))
print(round(4.125, 2), type(round(4.125, 2)))
print(round(4.126, 2), type(round(4.126, 2)))
print(round(2.5), type(round(2.5)))
print(round(3.5), type(round(3.5)))
print(round(5), type(round(5)))
print(round(6), type(round(6)))
# 4.12 <class 'float'>
# 4.12 <class 'float'>
# 4.13 <class 'float'>
# 4.13 <class 'float'>
# 3.0 <class 'float'>
# 4.0 <class 'float'>
# 5 <class 'int'>
# 6 <class 'int'>
Compare
import math
from timeit import timeit
from decimal import Decimal, ROUND_HALF_UP
def round1(number, ndigits=None):
exp = Decimal('1.{}'.format(ndigits * '0')) if ndigits else Decimal('1')
return type(number)(Decimal(number).quantize(exp, ROUND_HALF_UP))
def round2(number, ndigits=0):
exp = number * 10 ** ndigits
if abs(exp) - abs(math.floor(exp)) < 0.5:
return type(number)(math.floor(exp) / 10 ** ndigits)
return type(number)(math.ceil(exp) / 10 ** ndigits)
print(timeit('round1(123456789.1223456789, 5)', globals=globals()))
print(timeit('round2(123456789.1223456789, 5)', globals=globals()))
# 1.9912803000000001
# 1.2140076999999998
The math one is faster.