Bóia de arredondamento em Ruby

150

Estou tendo problemas para arredondar. Eu tenho um float, que eu quero arredondar para o centésimo de um decimal. No entanto, só posso usar o .roundque basicamente o transforma em int, o que significa que 2.34.round # => 2. existe uma maneira simples de fazer algo como2.3465 # => 2.35

user211662
fonte

Respostas:

181

Ao exibir, você pode usar (por exemplo)

>> '%.2f' % 2.3465
=> "2.35"

Se você deseja armazená-lo arredondado, pode usar

>> (2.3465*100).round / 100.0
=> 2.35
Peter
fonte
2
Obrigado. Não sabia que a sprintf cuidaria de arredondar para mim. sprintf '%.2f', 2.3465também funciona.
Noah Sussman
66
value.round (2) é melhor que esta solução
Kit Ho
12
Tenha em mente que 2.3000.round(2) => 2.3e sprintf '%.2f', 2.300 => 2.30. Na minha opinião, isso é uma falha no round (), ou deveria ter uma opção para preservar os zeros à direita.
Excalibur
14
@Excalibur 2.3000.round(2)é um número, não uma string. Não há como o número 2.3ser diferente 2.30, portanto, não há como ter uma opção para preservar zeros à direita. Você pode criar sua própria classe de numbers_with_significance, mas já temos strings.
Roobie Nuby
6
Note-se que embora este não trabalho para duas casas decimais, há uma falha no '%.3f' % 1.2345(3 casas decimais, não 2), no entanto !! O mesmo sprintftambém. Cuidado. Que irá retornar => 1.234 não => 1.235 como a maioria seria de esperar (IOW, após a segunda decimal, rodadas sprintf 5 para baixo e só arredonda um 6 para cima). É por isso que o comentário de Kit Ho acima tem mais de 25 votos positivos. Mais seguro de usar, '%.3f' % 1.2345.round(3)o número é arredondado corretamente .roundprimeiro e depois formatado (com zeros à direita, se necessário).
likethesky
392

Passe um argumento para arredondar contendo o número de casas decimais para arredondar para

>> 2.3465.round
=> 2
>> 2.3465.round(2)
=> 2.35
>> 2.3465.round(3)
=> 2.347
Steve Weet
fonte
8
Isso parece mais sensato do que multiplicar, arredondar e dividir. +1
Mark Embling 13/01/10
3
Hmm, esse método não parece estar no ruby ​​1.8.7. Talvez em 1.9?
Brian Armstrong
2
@Brian. Definitivamente, este é o 1.9 e também está nos rails (Com os quais esta pergunta foi marcada) #
Steve Weet 28/02/11
3
O método round do Ruby 1.8.7 não tem essa capacidade, adicionar o parâmetro de arredondamento com casas decimais é uma habilidade 1.9
bobmagoo
1
Observe que você não obtém zeros à direita com isso, então 1.1.round(2)=> 1.1não1.10
NotAnAmbiTurner 10/17/17
9

você pode usar isso para arredondar para uma precisão.

//to_f is for float

salary= 2921.9121
puts salary.to_f.round(2) // to 2 decimal place                   

puts salary.to_f.round() // to 3 decimal place          
pão de tecnologia
fonte
7

Você pode adicionar um método na classe Float, eu aprendi isso no stackoverflow:

class Float
    def precision(p)
        # Make sure the precision level is actually an integer and > 0
        raise ArgumentError, "#{p} is an invalid precision level. Valid ranges are integers > 0." unless p.class == Fixnum or p < 0
        # Special case for 0 precision so it returns a Fixnum and thus doesn't have a trailing .0
        return self.round if p == 0
        # Standard case  
        return (self * 10**p).round.to_f / 10**p
    end
end
Albert Català
fonte
3

Você também pode fornecer um número negativo como argumento ao roundmétodo para arredondar para o múltiplo mais próximo de 10, 100 e assim por diante.

# Round to the nearest multiple of 10. 
12.3453.round(-1)       # Output: 10

# Round to the nearest multiple of 100. 
124.3453.round(-2)      # Output: 100
BrunoFacca
fonte
2
def rounding(float,precision)
    return ((float * 10**precision).round.to_f) / (10**precision)
end
PeteJLeonard
fonte
2

que tal (2.3465*100).round()/100.0?

thenoviceoof
fonte
1

Se você apenas precisar exibi-lo, eu usaria o auxiliar number_with_precision . Se você precisar em outro lugar, eu usaria, como Steve Weet apontou, o roundmétodo

Fer
fonte
1
Observe que number_with_precisioné o método somente Rails.
Smar
0

Para o ruby ​​1.8.7, você pode adicionar o seguinte ao seu código:

class Float
    alias oldround:round
    def round(precision = nil)
        if precision.nil?
            return self
        else
            return ((self * 10**precision).oldround.to_f) / (10**precision)
        end 
    end 
end
Robert
fonte