Pregunta

En Ruby, quiero convertir un flotador a un int si se trata de un número entero. Por ejemplo

a = 1.0
b = 2.5

a.to_int_if_whole # => 1
b.to_int_if_whole # => 2.5

Básicamente estoy tratando de evitar mostrar" 0.0" en cualquier número que no tiene un número decimal. Estoy buscando una manera elegante (o integrado) hacer

def to_int_if_whole(float)
  (float % 1 == 0) ? float.to_i : float
end
¿Fue útil?

Solución 3

Esta es la solución que terminó trabajando de la manera que yo quiero que:

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

De esta manera puedo actualizar la lógica is_whole? (I parece Tadman de es el más sofisticado) si es necesario, y asegura que en cualquier lugar a salidas de flotador a una cadena (por ejemplo, en una forma) Parece como yo quiero a (es decir, no hay ceros en el extremo).

Gracias a todos por sus ideas - que realmente ayudó.

Otros consejos

Una forma sencilla de que sería:

class Float
  def prettify
    to_i == self ? to_i : self
  end
end

Esto se debe a:

irb> 1.0 == 1
=> true
irb> 1 == 1.0
=> true

A continuación, usted podría hacer:

irb> 1.0.prettify
=> 1

irb> 1.5.prettify
=> 1.5

A sprintf un trazador de líneas ...

sprintf("%g", 5.0)
=> "5"

sprintf("%g", 5.5)
=> "5.5"

Estoy no sabe mucho sobre Ruby.

Pero esto es una pantalla tema. Yo estaría muy sorprendido si las bibliotecas que está utilizando no tienen una manera de dar formato a un número cuando se convierte en una cadena.

Puede que no haya un cajón de sastre opción de formato que hace exactamente lo que quiere, pero se podía establecer un método que devuelve verdadero si el flotador es la representación de flotación de un número entero y false en caso contrario. Dentro de una rutina de formato que crear (por lo que sólo tiene que hacer esto una vez en su lugar) acaba de cambiar el formato basado en si esto es cierto o falso.

Este discute cómo controlar el número de dígitos que aparecen después del decimal cuando mostrando un número.

Cuidado con las complejidades de las representaciones de punto flotante. Matemáticas podría decir que la respuesta es 3 pero puede llegar 3,000000000000000000001. Me gustaría sugerir el uso de un delta para ver si el número es casi un número entero.

A pesar de que yo tiendo a estar de acuerdo con el comentario anterior, si usted debe hacer esto:

(float == float.floor) ? float.to_i : float

Si está utilizando rieles se puede usar con la opción de ayuda number_to_rounded strip_insignificant_zeros, por ejemplo:

ActiveSupport::NumberHelper.number_to_rounded(42.0, strip_insignificant_zeros: true)

o como esto:

42.0.to_s(:rounded, strip_insignificant_zeros: true)

Aquí está mi aplicación terriblemente hacktastic proporcionan para los propósitos educativos:

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 razón de usar la llamada al estilo sprintf es que se encarga de punto flotante aproximaciones mucho más fiable que el método de flotación redonda # tiende a.

No sé mucho sobre Ruby tampoco.

Pero en C ++, lo haría esto:

bool IsWholeNumber( float f )
{
    const float delta = 0.0001;
    int i = (int) f;
    return (f - (float)i) < delta;
}

Y entonces yo formato a la precisión de salida en base a eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top