Rubino rotondo float a int se il numero intero
-
21-08-2019 - |
Domanda
In ruby, voglio convertire un galleggiante per un int se si tratta di un numero intero. Ad esempio
a = 1.0
b = 2.5
a.to_int_if_whole # => 1
b.to_int_if_whole # => 2.5
In sostanza sto cercando di evitare la visualizzazione" 0,0" su qualsiasi numero che non ha un numero decimale. Sto cercando un modo elegante (o built-in) per fare
def to_int_if_whole(float)
(float % 1 == 0) ? float.to_i : float
end
Soluzione 3
Questa è la soluzione che ha finito per lavorare il modo in cui voglio che:
class Float
alias_method(:original_to_s, :to_s) unless method_defined?(:original_to_s)
def is_whole?
self % 1 == 0
end
def to_s
self.is_whole? ? self.to_i.to_s : self.original_to_s
end
end
In questo modo posso aggiornare il is_whole?
logica (I sembra Tadman di è il più sofisticato), se necessario, e assicura che ovunque a uscite Float a una stringa (ad esempio, in una forma) appare come voglio a (cioè, zeri sul lato frontale).
Grazie a tutti per le vostre idee - hanno veramente aiutato.
Altri suggerimenti
Un modo semplice per sarebbe:
class Float
def prettify
to_i == self ? to_i : self
end
end
Questo perché:
irb> 1.0 == 1
=> true
irb> 1 == 1.0
=> true
Poi si potrebbe fare:
irb> 1.0.prettify
=> 1
irb> 1.5.prettify
=> 1.5
Uno sprintf uno di linea ...
sprintf("%g", 5.0)
=> "5"
sprintf("%g", 5.5)
=> "5.5"
Sono non so molto di Ruby.
Ma questo è un Display problema. Sarei estremamente sorpreso se le librerie che si sta utilizzando non hanno un modo per formattare un numero quando si converte in una stringa.
Non ci potrebbe essere un catch-all opzione di formattazione che fa esattamente ciò che si vuole, ma è possibile impostare un metodo che restituisce vero se il galleggiante è la rappresentazione galleggiante di un numero intero e false altrimenti. All'interno di una routine di formattazione che si crea (in modo da avere solo a fare questo in una volta posto) basta cambiare la formattazione in base a se questo è vero o falso.
Questo discute come controllare il numero di cifre che compaiono dopo il decimale durante la visualizzazione di un numero.
Attenzione per la complessità del floating point rappresentazioni. Math potrebbe dire che la risposta è 3, ma si può ottenere 3,000000000000000000001. Io suggerirei di usare un delta per vedere se il numero è quasi un numero intero.
Anche se mi piacerebbe tendenzialmente d'accordo con il post di cui sopra, se si deve fare questo:
(float == float.floor) ? float.to_i : float
Se si utilizza rotaie è possibile utilizzare helper number_to_rounded
con l'opzione strip_insignificant_zeros
, ad esempio:
ActiveSupport::NumberHelper.number_to_rounded(42.0, strip_insignificant_zeros: true)
o come questo:
42.0.to_s(:rounded, strip_insignificant_zeros: true)
Ecco la mia implementazione orribilmente hacktastic prevista per scopi didattici:
class Float
def to_int_if_whole(precision = 2)
("%.#{precision}f" % self).split(/\./).last == '0' * precision and self.to_i or self
end
end
puts 1.0.to_int_if_whole # => 1
puts 2.5.to_int_if_whole # => 2.5
puts 1.9999999999999999999923.to_int_if_whole # => 2
La ragione per usare la chiamata sprintf stile è che gestisce floating point approssimazioni molto più affidabile rispetto al metodo rotonda Float # tende a.
Non so molto su di Ruby sia.
Ma in C ++, farei questo:
bool IsWholeNumber( float f )
{
const float delta = 0.0001;
int i = (int) f;
return (f - (float)i) < delta;
}
E poi mi piacerebbe formattare la precisione di uscita in base a questo.