Arredondando números em Ruby

Artigos - 15/Jul/2020 - por Luis Arantes

Vamos tratar nesta postagem de arredondamento de números em Ruby. A linguagem possui três métodos na classe Float focados para esta tarefa que serão descritos em detalhes a seguir. Os três métodos atuam em números do tipo float e podem retornar um float ou integer dependendo dos parâmetros que forem passados.

Ceil

É utilizado para arredondar o número para cima.

Se não for passado nenhum parâmetro, será retornado o próximo número do tipo integer.

2.47.ceil # retorna um Integer
=> 3

Se for informado um número positivo como parâmetro, o retorno do método será um número do tipo float contendo uma quantidade de casas decimais igual à do parâmetro informado.

2.47.ceil(1) # mantém uma casa decimal no arredondamento
=> 2.5
7.74592.ceil(1)
=> 7.8

2.7772.ceil(2) # preserva duas casas decimais
=> 2.78
44.5189.ceil(2)
=> 44.52

Se o parâmetro for um valor negativo então os algarismos não fracionados é que serão arredondados para cima, seguindo as casas decimais de acordo com seus pesos. Os números fracionados neste caso são simplesmente descartados.

2344.56.ceil(-2) # arredonda unidades e dezenas para cima
=> 2400
635747.447.ceil(-3) # arredonda unidades, dezenas e centenas
=> 636000

Floor

O método floor faz exatamente o oposto de ceil, arredondando o número para baixo.

Por seguir o mesmo padrão de acordo com o parâmetro informado, também é possível arredondar tanto os valores fracionados quanto os valores inteiros do número.

2.626.floor # retorna um Integer
=> 2

2.626.floor(2) # preserva duas casas decimais
=> 2.62
35.43743722.floor(2) # também preserva duas casas decimais
=> 35.43

2647.floor(-3) # arredonda unidades, dezenas e centenas para baixo
=> 2000
666777888.999.floor(-4) # arredonda unidades, dezenas, centenas e milhares
=> 666770000

Round

Este método é o mais complexo dos três abordados aqui. Utilizando o round é possível arredondar o número para cima ou para baixo dependendo do valor inicial dos seus algarismos, e também dependendo dos parâmetros informados.

Chamar o round sem passar nenhum parâmetro faz o método avaliar a primeira casa decimal do número. Se este algarismo possuir valor entre 0 e 4, o dígito da unidade se manterá inalterado. Se o valor do algarismo for entre 5 e 9 será acrescentada uma unidade, arredondando o número para cima e retornando um número inteiro.

22.76.round # arredonda unidade para cima por causa do valor decimal 0,7
=> 23
19.214.round # arredonda para baixo por causa do 0,2
=> 19

Informar um número como parâmetro faz o round se comportar como se fosse o ceil e o floor, atuando na quantidade especificada de numerais correspondentes. Um parâmetro de valor positivo faz o número retornado manter esta mesma quantidade de casas decimais.

3.1415.round(2) # mantém duas casas decimais
=> 3.14 # arredondado para baixo
6.477691.round(3) # mantém três casas decimais
=> 6.478 # arredondado para cima

Um parâmetro de valor negativo afeta as casas não decimais, arredondando o dígito de maior peso e zerando os dígitos menores.

77634.72.round(-3) # arredonda centenas para cima
=> 78000
1434.4.round(-2) # arredonda dezenas para baixo
=> 1400
472.round(-3) # arredonda centenas para baixo
=> 0 # pela centena ser o dígito mais significativo o número é zerado!

O arredondamento do valor 5 pode ser alterado por meio de outro parâmetro que pode ser passado ao round. O método também aceita uma chave half com três valores diferentes:

half: :up # arredonda o valor para cima (padrão)
half: :down # arredonda o valor para baixo
half: :even # arredonda o valor em direção ao número par mais próximo

Vejamos alguns exemplos de uso abaixo:

414.5.round(half: :up) # arredonda para cima
=> 415 # dígito da unidade alterado

317.45.round(1, half: :down) # força o arredondamento para baixo na primeira casa decimal
=> 317.4 # com isso o dígito 4 é mantido

# 2 é o número par mais próximo nos casos abaixo
2.5.round(half: :even)
=> 2 # arredondamento vai para baixo
1.5.round(half: :even)
=> 2 # neste caso o arredondamento vai para cima

# 4 é o número par mais próximo em ambos os casos a seguir
33.35.round(1, half: :even)
=> 33.4 # arredondamento vai para cima
33.45.round(1, half: :even)
=> 33.4 # porém aqui o arredondamento vai para baixo

Arredondamento em números negativos

Há algumas diferenças de comportamento no uso de ceil, floor e round quando os números envolvidos são negativos.

O ceil e o floor continuarão obedecendo à progressão numérica, e por isso o arredondamento respeita o sinal negativo do número.

-42.5.ceil
=> -42 # -42 é um número de maior valor que -42.5
-42.5.floor
=> -43 # neste caso, -43 possui o menor valor

Já o round não se importa se o número avaliado é positivo ou negativo. O round literalmente vai fazer o que seu nome diz, que é arredondar o número onde o método foi chamado em direção ao número mais próximo.

-1.6.round # arredondamento será "para cima" por causa do 6
=> -2 # porém o número retornado possui menor valor por ser negativo

-3.74.round(1) # aqui o 4 faz o número ser arredondado para baixo
=> -3.7 # mas o número retornado possui maior valor

-4.5.round(half: :down)
=> -4 # o arredondamento "para baixo" gera um número de maior valor

Devido a este comportamento é importante ter uma atenção especial quando os números que precisamos arredondar são negativos. Dependendo da situação, talvez seja necessário fazer algum tratamento prévio deste número - como retornar o valor absoluto através do método abs - antes de fazer uso do ceil floor e round.

Foto de perfil do autor
Luis Arantes

Dev na Rebase

Desenvolvedor Ruby que gosta de falar sobre código, videogames e bandas de heavy metal obscuras