¿Cómo verifico si una cadena representa un número (flotante)?

9 minutos de lectura

avatar de usuario
daniel goldberg

¿Cómo verifico si una cadena representa un valor numérico en Python?

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

Lo anterior funciona, pero parece torpe.

  • ¿Qué tiene de malo tu solución actual? Es corto, rápido y legible.

    – Coronel Pánico

    21 de marzo de 2013 a las 22:52


  • Y no solo tiene que devolver Verdadero o Falso. En su lugar, puede devolver el valor modificado adecuadamente; por ejemplo, podría usar esto para poner comillas que no sean números.

    – Thruston

    24 mayo 2013 a las 21:33

  • ¿No sería mejor devolver el resultado de float(s) en el caso de una conversión exitosa? Todavía tiene la verificación de éxito (el resultado es Falso) y realmente TIENE la conversión, que es probable que desee de todos modos.

    – Jiminion

    25 de julio de 2013 a las 14:40

  • Aunque esta pregunta es más antigua, solo quería decir que esta es una forma elegante que está documentada como EAFP. Así que probablemente la mejor solución para este tipo de problema.

    – thiruvenkadam

    7 oct 2013 a las 15:42


  • No devuelve el resultado de float(s) o None en caso de error. si luego lo usas como x = float('0.00'); if x: use_float(x); ahora tienes un error en tu código. Los valores verdaderos son la razón por la que estas funciones generan una excepción en lugar de devolver None en primer lugar. Una mejor solución es simplemente evitar la función de utilidad y rodear la llamada para que flote en un try catch cuando quieras usarlo.

    – ovalado

    5 de enero de 2016 a las 7:31


avatar de usuario
S. Lott

Que, no solo es feo y lento

Disputaría ambos.

Una expresión regular u otro método de análisis de cadenas sería más feo y más lento.

No estoy seguro de que algo más pueda ser más rápido que lo anterior. Llama a la función y regresa. Try/Catch no introduce mucha sobrecarga porque la excepción más común se captura sin una búsqueda exhaustiva de marcos de pila.

El problema es que cualquier función de conversión numérica tiene dos tipos de resultados

  • Un número, si el número es válido
  • Un código de estado (p. ej., a través de errno) o una excepción para mostrar que no se pudo analizar ningún número válido.

C (como ejemplo) soluciona esto de varias maneras. Python lo expone clara y explícitamente.

Creo que tu código para hacer esto es perfecto.

  • No creo que el código sea perfecto (pero creo que está muy cerca): es más habitual poner solamente la parte que se “prueba” en el try cláusula, así que pondría la return True en un else cláusula de la try. Una de las razones es que con el código en la pregunta, si tuviera que revisarlo, tendría que verificar que la segunda declaración en el try La cláusula no puede generar un ValueError: concedido, esto no requiere demasiado tiempo o capacidad mental, pero ¿por qué usar alguno cuando no se necesita ninguno?

    – Eric O Lebigot

    5 de julio de 2013 a las 8:21


  • La respuesta parece convincente, pero me hace preguntarme por qué no se proporciona lista para usar… Copiaré esto y lo usaré en cualquier caso.

    – sabio

    28 de diciembre de 2013 a las 23:40

  • Que horrible. ¿Qué tal si no me importa cuál es el número? es ¿solo que es un número (que es lo que me trajo aquí)? En lugar de una línea 1 IsNumeric() Termino con un intento/captura u otro envolviendo un intento/captura. Puaj

    – Básico

    10 de marzo de 2014 a las 11:22


  • No se proporciona ‘listo para usar’ porque if is_number(s): x = float(x) else: // fail es el mismo número de líneas de código que el try: x = float(x) catch TypeError: # fail. Esta función de utilidad es una abstracción completamente innecesaria.

    – ovalado

    5 de enero de 2016 a las 7:34


  • Pero la abstracción es el punto central de las bibliotecas. Tener una función ‘isNumber’ (en cualquier idioma) ayuda mucho porque puede construirla directamente en declaraciones if y tener un código mucho más legible y mantenible que depender de los bloques try – catch. Además, si necesita usar el código más de una vez en más de una clase/módulo, habrá usado más líneas de código de las que tendría una función integrada.

    – JamEngulfer

    18 de marzo de 2016 a las 11:19

  • para buenos gráficos +1. Vi el punto de referencia y vi el gráfico, todo lo de TL; DR se volvió claro e intuitivo.

    – jcchuks

    18/11/2016 a las 18:35

  • Este método no maneja números negativos (guiones). Recomendaría usar simplemente el método de flotación, ya que es menos propenso a errores y funcionará siempre.

    – Erizo

    10 de abril de 2019 a las 15:55

  • Lo que es importante tener en cuenta es que, incluso suponiendo que no puede haber un guión, el método replace-isdigit solo es más rápido para los que no son números (resultado falso), mientras que el método try-except es más rápido para los números (resultado verdadero). Si la mayor parte de su entrada es una entrada válida, ¡está mejor con la solución probar-excepto!

    –Markus von Broady

    24 de abril de 2019 a las 12:43


  • No funciona en notación exponencial como '1.5e-9' o en negativos.

    – EL_DON

    17 oct 2019 a las 19:03

  • Brillante, aparte de las advertencias obvias de falsos negativos para exponenciación y negativos, que puede corregir trivialmente simplemente encadenando s.replace() llamadas Por ejemplo, s.replace('.','',1).replace('e-','',1).replace('e','',1).isdigit() maneja la exponenciación. Para luego manejar los negativos, simplemente tira a la izquierda el primer carácter si es un guión. Por ejemplo, s.lstrip('-').replace('.','',1).replace('e-','',1).replace('e','',1).isdigit(). Sí, probé exhaustivamente ese one-liner y puedo confirmar que se comporta como se esperaba.

    –Cecil Curry

    25 de septiembre de 2020 a las 0:59

Hay una excepción que quizás desee tener en cuenta: la cadena ‘NaN’

Si desea que is_number devuelva FALSO para ‘NaN’, este código no funcionará ya que Python lo convierte en su representación de un número que no es un número (hablar sobre problemas de identidad):

>>> float('NaN')
nan

De lo contrario, debería agradecerle por el fragmento de código que ahora uso mucho. 🙂

GRAMO.

  • Realmente, NaN podría ser un buen valor para devolver (en lugar de False) si el texto pasado no es de hecho una representación de un número. Verificarlo es una especie de dolor (Python’s float type realmente necesita un método para ello), pero puede usarlo en los cálculos sin producir un error, y solo necesita verificar el resultado.

    – tipo todo

    10 de junio de 2011 a las 17:50

  • Otra excepción es la cadena 'inf'. O inf o NaN también se puede prefijar con un + o - y aún ser aceptado.

    – agf

    22 mayo 2012 a las 23:10

  • Si desea devolver False para NaN e Inf, cambie la línea a x = float(s); devuelve (x == x) y (x – 1 != x). Esto debería devolver True para todos los flotantes excepto Inf y NaN

    – RyanN

    15/03/2013 a las 20:29


  • x-1 == x es cierto para flotadores grandes más pequeños que inf. Desde Python 3.2 puedes usar math.isfinite para probar números que no son ni NaN ni infinitos, o verificar ambos math.isnan y math.isinf antes de eso.

    –Steve Jessop

    22 de enero de 2014 a las 18:39


avatar de usuario
david c

Qué tal esto:

'3.14'.replace('.','',1).isdigit()

que devolverá verdadero solo si hay uno o ningún ‘.’ en la cadena de dígitos.

'3.14.5'.replace('.','',1).isdigit()

devolverá falso

editar: acabo de ver otro comentario … agregando un .replace(badstuff,'',maxnum_badstuff) para otros casos se puede hacer. si está pasando sal y no condimentos arbitrarios (ref:xkcd#974) esto irá bien 😛

  • Realmente, NaN podría ser un buen valor para devolver (en lugar de False) si el texto pasado no es de hecho una representación de un número. Verificarlo es una especie de dolor (Python’s float type realmente necesita un método para ello), pero puede usarlo en los cálculos sin producir un error, y solo necesita verificar el resultado.

    – tipo todo

    10 de junio de 2011 a las 17:50

  • Otra excepción es la cadena 'inf'. O inf o NaN también se puede prefijar con un + o - y aún ser aceptado.

    – agf

    22 mayo 2012 a las 23:10

  • Si desea devolver False para NaN e Inf, cambie la línea a x = float(s); devuelve (x == x) y (x – 1 != x). Esto debería devolver True para todos los flotantes excepto Inf y NaN

    – RyanN

    15/03/2013 a las 20:29


  • x-1 == x es cierto para flotadores grandes más pequeños que inf. Desde Python 3.2 puedes usar math.isfinite para probar números que no son ni NaN ni infinitos, o verificar ambos math.isnan y math.isinf antes de eso.

    –Steve Jessop

    22 de enero de 2014 a las 18:39


Actualizado después de que Alfe señaló que no es necesario verificar el flotador por separado, ya que los complejos manejan ambos:

def is_number(s):
    try:
        complex(s) # for int, long, float and complex
    except ValueError:
        return False

    return True

Dicho anteriormente: en algunos casos raros, es posible que también deba verificar los números complejos (por ejemplo, 1 + 2i), que no se pueden representar con un flotador:

def is_number(s):
    try:
        float(s) # for int, long and float
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False

    return True

  • No estoy de acuerdo. Eso es MUY improbable en el uso normal, y sería mejor crear una llamada is_complex_number() para cuando los esté usando, en lugar de sobrecargar una llamada con una operación adicional para una probabilidad de operación incorrecta del 0.0001%.

    – Jiminion

    25 de julio de 2013 a las 14:43

  • Puedes desnudar el float() cosas por completo y solo verifique el complex() llamada para tener éxito. Todo analizado por float() puede ser analizado por complex().

    – Alfé

    22 de abril de 2016 a las 9:31

  • Esta función devolverá los valores NaNs e Inf de Pandas como valores numéricos.

    – reparador

    29 de mayo de 2016 a las 11:51

  • complex('(01989)') regresará (1989+0j). Pero float('(01989)') fallará. Entonces creo que usar complex no es buena idea

    – por favor

    20 de diciembre de 2018 a las 15:19

  • ¡Ay! extraño eso complex() acepta (– y )-sintaxis delimitada: presumiblemente para dar cuenta de la suma de vectores compuestos en el plano imaginario subyacente a los números complejos, pero aún así. Como sugiere @plhn, usando complex() aquí invita a los falsos positivos. No hagas esto en el código de producción. Honestamente, s.lstrip('-').replace('.','',1).replace('e-','',1).replace('e','',1).isdigit() sigue siendo la solución óptima para la mayoría de los casos de uso.

    –Cecil Curry

    25 de septiembre de 2020 a las 1:07


¿Ha sido útil esta solución?