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
.