¿Cómo puedo comprobar si un valor es un número?

82

Quiero simplemente verificar si un valor devuelto de un campo de texto de formulario es un número, es decir: 12, 12.5 o 12.75. ¿Existe una forma sencilla de comprobar esto, especialmente si el valor se extrae como param?

usuario211662
fuente
um, lo único es que el código funciona para is_a_number? funciona con la única excepción de .02 o .3 números ....
user211662
7
Prefiero esta solución: stackoverflow.com/questions/5661466/… No sé por qué tanta gente piensa que una expresión regular sería mejor para eso.
2called-caos

Respuestas:

26

Simplemente regexp, es trivial, y no vale la pena pensar más allá de eso:

v =~ /\A[-+]?[0-9]*\.?[0-9]+\Z/

(Corregido según el comentario de Justin)

cwninja
fuente
5
En ruby, ^ y $ denotan el comienzo / final de una línea, no de una cadena. Esto hace que esto sea ineficaz para usarlo como un medio para desinfectar las entradas (consulte guides.rubyonrails.org/security.html#regular-expressions ). Un mejor enfoque sería: v.to_s =~ /\A[-+]?\d*\.?\d+\z/.
Justin
204

Puedes usar

12.is_a? Numeric

( Numericfuncionará para enteros y flotantes).

Si llega como una cadena que puede contener una representación de un número válido, puede usar

class String
  def valid_float?
    true if Float self rescue false
  end
end

y luego '12'.valid_float?devolverá verdadero si puede convertir la cadena en un flotante válido (por ejemplo, con to_f).

Pedro
fuente
Lo siento, esto es Ruby on Rails ... Básicamente, solo quiero poder evaluar cualquier entrada del usuario, ya sea .03 0.3, 2.2 Los dos últimos funcionan, pero necesito que funcione la primera entrada: S
user211662
10
Fixnumno parece funcionar con flotadores. Sin embargo, Numericfunciona bien. Entonces 1.234.is_a? Fixnum == false, pero 1.234.is_a? Numeric == true.
KurtPreston
Esto no funciona con flotadores. Debe usar 1.1.is_a? NumericVer stackoverflow.com/a/17668654/76486
Brian Armstrong
1
No funciona para mí :(pry(main)> '12'.is_a? Numeric => false
Salil
@Salil obviamente eso no funcionará para ti, '12'es un String. En ese caso, verifique la cadena con Regex o cualquier otra solución posible.
edmundo096
27

Por lo general, solo uso Integer y Float en estos días.

1.9.2p320 :001 > foo = "343"
 => "343"
1.9.2p320 :003 > goo = "fg5"
 => "fg5"

1.9.2p320 :002 > Integer(foo) rescue nil
 => 343
1.9.2p320 :004 > Integer(goo) rescue nil
 => nil

1.9.2p320 :005 > Float(foo) rescue nil
 => 343.0
1.9.2p320 :006 > Float(goo) rescue nil
 => nil
daesu
fuente
7

Simplemente convierta la cadena dos veces:

num = '12'
num == num.to_i.to_s 
#=> true 

num = '3re'
num == num.to_i.to_s 
#=> false
Evan Ross
fuente
No funciona tan mal con números enteros, pero hay muchas formas de fallar si quieres seguir este consejo con flotadores (que es sobre lo que pregunta la pregunta): "7" == "7".to_f.to_s #=> false("7" vs "7.0")
David Stosik
You can donum == num.to_i.to_s || num == num.to_f.to_s
mannykary
también puede formatear ambas cadenas usando el operador "%" para garantizar que ambas terminen en la misma cadena
Jaacko Torus
5

Sugeriría este

def is_number?
  self.to_f == self
end

> 15.is_number?
=> true
> 15.0.is_number?
=> true
> 'Not a number'.is_number?
=> false
> (0/0.0).is_number?
=> false
installero
fuente
4
irb(main):005:0> 1.1.is_a? Numeric
=> true
irb(main):006:0> 1.is_a? Numeric
=> true
irb(main):007:0> 'asd'.is_a? Numeric
=> false
Brian Armstrong
fuente
6
"1.1" .es_a? Numérico => falso
Waclock
¿Cómo abordaría el problema de la conversión de cadenas? OP dice que es de un campo de texto.
Schlingel
-5

Los valores de cadena siempre se convierten a 0 con .to_i

[14] pry(main)> 'Apple'.to_i > 0
=> false

[15] pry(main)> '101'.to_i > 0
=> true
Adrian Teh
fuente
¿Qué pasa con los casos extremos? Si el número es 0 o negativo, su prueba dará un falso negativo.
tsikov
Peor aún, '1AB2' .to_i devolvería 1 para algo que claramente no es un entero ...
Thomas Bindzus