2011-08-17 13 views
12

Il movimento circolare lo arrotonda verso l'alto o verso il basso. Ho sempre bisogno di arrotondare.Un modo per arrotondare Galleggia verso il basso

Ho la soluzione ma non mi piace molto ... Forse c'è un modo migliore.

Questo è quello che voglio:

1.9999.round_down(2) 
#=> 1.99 
1.9901.round_down(2) 
#=> 1 

mi si avvicinò con questa soluzione, ma mi piacerebbe sapere se esiste una soluzione migliore (Non mi piace che mi converto il galleggiante due volte). C'è già un metodo per questo? Perché mi è sembrato strano che non potessi trovarlo.

class Float 
    def round_down(n=0) 
    ((self * 10**n).to_i).to_f/10**n 
    end 
end 

Grazie.

+0

mi piace la vostra soluzione ... – reto

+0

Cosa vuoi a che fare con i numeri negativi?Verso l'infinito negativo o verso lo zero? – l0b0

+0

Non è esattamente quello che vuoi (dal momento che perdi sempre la parte decimale), ma se converti in un numero intero, arrotonderai sempre - '1.9901.to_i' - può essere molto meglio a seconda del tuo scenario. –

risposta

9

Sulla base della risposta di @kimmmo, questo dovrebbe essere un po 'più efficiente:

class Float 
    def round_down n=0 
    s = self.to_s 
    l = s.index('.') + 1 + n 
    s.length <= l ? self : s[0,l].to_f 
    end 
end 

1.9991.round_down(3) 
=> 1.999 
1.9991.round_down(2) 
=> 1.99 
1.9991.round_down(0) 
=> 1.0 
1.9991.round_down(5) 
=> 1.9991 

o in base alla risposta da @steenslag, probabilmente ancora più efficiente in quanto non v'è alcuna conversione di stringhe:

class Float 
    def round_down n=0 
    n < 1 ? self.to_i.to_f : (self - 0.5/10**n).round(n) 
    end 
end 
+0

Anche questa risposta è buona. Ancora preferisco @kimmmo la sua soluzione perché è più breve e più facile da leggere. Ma questa è anche una buona risposta! Grazie –

+0

@michaelkoper: guarda la seconda soluzione - penso che sia più semplice e tuttavia più efficiente. – geronime

+3

Nel mio test rapido della velocità, questa versione della stringa è circa due volte più veloce della versione 'split' di kimmmo, e la seconda versione che utilizza la matematica effettiva è ancora circa 4 volte più veloce. Matematica: buona per i numeri. –

4

è possibile utilizzare il metodo piano

http://www.ruby-doc.org/core/classes/Float.html#M000142

+0

Float # floor non girerà mai 1.999 in 1.99. –

+0

Penso che floor sia lo stesso di to_i. Restituisce il numero intero più alto. –

+0

Questa è la risposta corretta. Potresti aver aggiunto un esempio. –

36
1.9999.to_i 
#=> 1 
1.9999.floor 
#=> 1 

risposto 1 secondi fa fl00r

"%.2f" % 1.93213 
#=> 1.93 

@kimmmo è giusto.

class Float 
    def round_down(n=0) 
    self.to_s[/\d+\.\d{#{n}}/].to_f 
    end 
end 
+1

'"% .2f "% 1.935 => 1.94', il richiedente vuole che restituisca 1.93 –

+0

@kimmmo, oh, ho capito – fl00r

8

Sembra che si vuole solo mettere a nudo decimali dopo n

class Float 
    def round_down(n=0) 
    int,dec=self.to_s.split('.') 
    "#{int}.#{dec[0...n]}".to_f 
    end 
end 


1.9991.round_down(3) 
=> 1.999 
1.9991.round_down(2) 
=> 1.99 
1.9991.round_down(0) 
=> 1.0 
1.9991.round_down(10) 
=> 1.9991 

(Edit: versione leggermente più efficiente senza la regexp)

+0

Ehi, mi piace questa idea! –

+0

Non dovrebbe '1.9991.round_down (0)' restituire '1' invece di' 1.0'? – Mischa

+0

@mischa '1.0' vuol dire che è ancora un float. Suppongo che potresti creare funzionalità per usare 'to_i' se' n == 0', ma questo potrebbe probabilmente dare a qualcuno il debug di mal di testa. – brymck

1

In Ruby 1.9:

class Float 
    def floor_with_prec(prec = 0) 
    (self - 0.5).round(prec) 
    end 
end 
+0

'(1.9990 - 0.5) .round (2)' => 1.5 (asker vuole restituire 1.99) –

+1

@kimmmo Destra. Puoi aggirare il problema con una revisione minore, penso: '(auto - 0.5/10 ** prec) .round (prec)'. Non sono sicuro se questo verrà battuto da problemi in virgola mobile, però. – brymck

1
class Float 
    def rownd_down(digits = 1) 
    ("%.#{digits+1}f" % self)[0..-2].to_f 
    end 
end 

> 1.9991.rownd_down(3) 
=> 1.999 
> 1.9991.rownd_down(2) 
=> 1.99 
> 1.9991.rownd_down(10) 
> 1.9991 
-1

Questo ha funzionato per me.

> (1.999).to_i.to_f 

Per arrotondamento si potrebbe utilizzare

> (1.999+1).to_i.to_f 
0
class Float 
    def round_down(n) 
    num = self.round(n) 
    num > self ? (num - 0.1**n) : num 
    end 
end 

56.0.round_down(-1) = 50. Funziona anche con numeri negativi, se si accetta che l'arrotondamento rende un numero più piccolo: -56.09.round_down(1) = -56.1.

0

trovato questo articolo utile: https://richonrails.com/articles/rounding-numbers-in-ruby

Ecco il giro su e giù per i metodi:

class Float 
    def round_down(exp = 0) 
    multiplier = 10 ** exp 
    ((self * multiplier).floor).to_f/multiplier.to_f 
    end 

    def round_up(exp = 0) 
    multiplier = 10 ** exp 
    ((self * multiplier).ceil).to_f/multiplier.to_f 
    end 
end 
Problemi correlati