Dúvidas sobre a estratégia ROUND_HALF_UP
:
- Por que essa estratégia faz os números negativos ficarem ainda menores? Exemplo: -1,55 => -1,6
- Por que essa estratégia não arredonda todos os decimais em vez de só o último? Na real, essa é uma pergunta para todas as estratégias de arredondamento. Exemplo: 1,245 => 1.2
Quais alternativas existem?
Eu gostaria de usar algo como o ROUND_HALF_UP
, mas que:
- Considerasse os valores de todas as casas decimais
- Sempre tivesse tendência ao infinito positivo
- Só tomasse ação quando tivesse um valor na casa decimal acima de 5
Eu criei o código que preciso, mas eu gostaria de saber se já existe alguma biblioteca pronta com esse modo, ou se o próprio Python já tem alguma solução pronta.
Segue o código que fiz. Os valores da função round_half_up
(os da esquerda), são os que eu quero receber:
from decimal import Decimal, ROUND_HALF_DOWN, ROUND_DOWN, ROUND_HALF_UP
def to_decimal(value):
return Decimal(str(value))
def round_to(value, decimals=0, strategy=ROUND_HALF_UP):
precision = Decimal('1.' + '0' * decimals)
return to_decimal(value).quantize(precision, strategy)
def round_half_up(value, decimals=0):
value = to_decimal(value)
if value > 0:
value = _aux_round_up(value, decimals)
return round_to(value, decimals, ROUND_HALF_DOWN)
def _aux_round_up(value, decimals):
multiplier = 10 ** decimals
multiplied_value = (value * multiplier).normalize()
_, extra_decimals = str(multiplied_value).split('.')
extra_decimals = len(extra_decimals)
aux_value = '0.' + ('5' * extra_decimals)
aux_value = Decimal(aux_value)
return (multiplied_value + aux_value).quantize(Decimal('1.'), ROUND_DOWN) / multiplier
print('1 decimal')
print(round_half_up(1.23, 1), round_to(1.23, 1)) # 1.2 | 1.2
print(round_half_up(1.25, 1), round_to(1.25, 1)) # 1.3 | 1.3
print(round_half_up(1.235, 1), round_to(1.235, 1)) # 1.2 | 1.2
print(round_half_up(1.245, 1), round_to(1.245, 1)) # 1.3 | 1.2
print('2 decimals')
print(round_half_up(1.234, 2), round_to(1.234, 2)) # 1.23 | 1.23
print(round_half_up(1.235, 2), round_to(1.235, 2)) # 1.24 | 1.24
print(round_half_up(1.2344, 2), round_to(1.2344, 2)) # 1.23 | 1.23
print(round_half_up(1.2345, 2), round_to(1.2345, 2)) # 1.24 | 1.23
print('negative number, 1 decimal')
print(round_half_up(-1.23, 1), round_to(-1.23, 1)) # -1.2 | -1.2
print(round_half_up(-1.25, 1), round_to(-1.25, 1)) # -1.2 | -1.3
print(round_half_up(-1.235, 1), round_to(-1.235, 1)) # -1.2 | -1.2
print(round_half_up(-1.245, 1), round_to(-1.245, 1)) # -1.2 | -1.2
print('negative number, 2 decimals')
print(round_half_up(-1.234, 2), round_to(-1.234, 2)) # -1.23 | -1.23
print(round_half_up(-1.235, 2), round_to(-1.235, 2)) # -1.23 | -1.24
print(round_half_up(-1.2344, 2), round_to(-1.2344, 2)) # -1.23 | -1.23
print(round_half_up(-1.2345, 2), round_to(-1.2345, 2)) # -1.23 | -1.23