¿Cuál es el equivalente en C # de NaN o IsNumeric?

103

¿Cuál es la forma más eficiente de probar una cadena de entrada si contiene un valor numérico (o, por el contrario, no es un número)? Supongo que puedo usar Double.Parseo una expresión regular (ver más abajo) pero me preguntaba si hay alguna forma integrada de hacer esto, como javascript NaN()o IsNumeric()(¿era VB, no puedo recordar?).

public static bool IsNumeric(this string value)
{
    return Regex.IsMatch(value, "^\\d+$");
}
johnc
fuente
1
Posible duplicado de ¿Cómo identifico si una cadena es un número?
Michael Freidgeim

Respuestas:

176

Esto no tiene la sobrecarga de expresiones regulares

double myNum = 0;
String testVar = "Not A Number";

if (Double.TryParse(testVar, out myNum)) {
  // it is a number
} else {
  // it is not a number
}

Por cierto, todos los tipos de datos estándar, con la flagrante excepción de los GUID, admiten TryParse.

update
secretwep mostró que el valor "2345" pasará la prueba anterior como un número. Sin embargo, si necesita asegurarse de que todos los caracteres dentro de la cadena sean dígitos, entonces debe tomar otro enfoque.

ejemplo 1 :

public Boolean IsNumber(String s) {
  Boolean value = true;
  foreach(Char c in s.ToCharArray()) {
    value = value && Char.IsDigit(c);
  }

  return value;
}

o si quieres ser un poco mas elegante

public Boolean IsNumber(String value) {
  return value.All(Char.IsDigit);
}

actualización 2 (de @stackonfire para tratar con cadenas nulas o vacías)

public Boolean IsNumber(String s) { 
    Boolean value = true; 
    if (s == String.Empty || s == null) { 
        value=false; 
    } else { 
        foreach(Char c in s.ToCharArray()) { 
            value = value && Char.IsDigit(c); 
        } 
    } return value; 
}
Yo no
fuente
Si es necesario, puede envolver el código anterior en un método de utilidad más útil como public static bool IsInteger (string sMaybeANumber)
Gishu
@Gishu: Tienes razón si lo único que te importa es si el número se puede convertir.
NotMe
2
El único problema con esto es que el Numberobjeto en Javascript es un flotante o un número entero, por lo que cambiar a doble. TryParse sería un equivalente más exacto
Chris S
7
Es posible que desee tener cuidado con esto, ya que las cadenas "NaN" e "Infinity" se analizan en a double, pero muchos los considerarían no numéricos.
Mike Zboray
1
Un ejemplo 1 corregido para tratar con cadenas nulas o vacías, que de otra manera estaban causando que IsNumber devolviera erróneamente verdadero: public Boolean IsNumber(String s) { Boolean value = true; if (s == String.Empty || s == null) { value=false; } else { foreach(Char c in s.ToCharArray()) { value = value && Char.IsDigit(c); } } return value; }
stackonfire
41

Prefiero algo como esto, te permite decidir qué NumberStyleprobar.

public static Boolean IsNumeric(String input, NumberStyles numberStyle) {
    Double temp;
    Boolean result = Double.TryParse(input, numberStyle, CultureInfo.CurrentCulture, out temp);
    return result;
}
Anthony Mastrean
fuente
7
+1 por ser la única persona hasta ahora en Double.TryParse en lugar de Int. TryParse :)
johnc
Obviamente, esto también es casi un método de extensión.
Anthony Mastrean
19

Además de las respuestas correctas anteriores, probablemente valga la pena señalar que "No es un número" (NaN) en su uso general no es equivalente a una cadena que no puede evaluarse como un valor numérico. Por lo general, NaN se entiende como un valor numérico utilizado para representar el resultado de un cálculo "imposible", cuando el resultado no está definido. A este respecto, diría que el uso de Javascript es un poco engañoso. En C #, NaN se define como una propiedad de los tipos numéricos simple y doble y se usa para referirse explícitamente al resultado de bucear cero por cero. Otros lenguajes lo utilizan para representar diferentes valores "imposibles".

Stu Mackellar
fuente
11

Sé que esto ha sido respondido de muchas maneras diferentes, con extensiones y ejemplos lambda, pero una combinación de ambos para la solución más simple.

public static bool IsNumeric(this String s)
{
    return s.All(Char.IsDigit);
}

o si está utilizando Visual Studio 2015 (C # 6.0 o superior), entonces

public static bool IsNumeric(this String s) => s.All(Char.IsDigit);

Impresionante C # 6 en una línea. Por supuesto, esto es limitado porque solo prueba solo caracteres numéricos.

Para usar, solo tenga una cadena y llame al método, como por ejemplo:

bool IsaNumber = "123456".IsNumeric();
Paul Bartlett
fuente
1
Para los usuarios que no estén familiarizados con los métodos de extensión , podría ser beneficioso incluir más información (o al menos la clase estática circundante para proporcionar un ejemplo más completo).
johnnyRose
No me gusta esta solución porque devolverá falso para números con un decimal. Podría ser útil para números enteros, pero si eso es lo que desea utilizar para el método deben ser renombrados EsEntero
technoman23
5

Sí, IsNumeric es VB. Por lo general, la gente usa el método TryParse (), aunque es un poco torpe. Como sugirió, siempre puede escribir el suyo.

int i;
if (int.TryParse(string, out i))
{

}
Ed S.
fuente
5

Me gusta el método de extensión, pero no me gusta lanzar excepciones si es posible. Opté por un método de extensión que toma la mejor de 2 respuestas aquí.

    /// <summary>
    /// Extension method that works out if a string is numeric or not
    /// </summary>
    /// <param name="str">string that may be a number</param>
    /// <returns>true if numeric, false if not</returns>
    public static bool IsNumeric(this String str)
    {
        double myNum = 0;
        if (Double.TryParse(str, out myNum))
        {
            return true;
        }
        return false;
    }
NER1808
fuente
4

Aún puede usar la función de Visual Basic en C #. Lo único que tienes que hacer es seguir mis instrucciones que se muestran a continuación:

  1. Agregue la referencia a la biblioteca de Visual Basic haciendo clic derecho en su proyecto y seleccionando "Agregar referencia":

ingrese la descripción de la imagen aquí

  1. Luego impórtelo en su clase como se muestra a continuación:

    utilizando Microsoft.VisualBasic;

  2. A continuación, utilícelo donde desee, como se muestra a continuación:

                if (!Information.IsNumeric(softwareVersion))
            {
                throw new DataException(string.Format("[{0}] is an invalid App Version!  Only numeric values are supported at this time.", softwareVersion));
            }

¡Espero que esto ayude y buena suerte!

Vincy
fuente
2
Si bien no recomendaría este método, es una respuesta correcta. No estoy seguro de por qué se votó en contra, y dado que tampoco se explicó por qué, voté a favor para contrarrestarlo :-)
Abacus
4

VB tiene la IsNumericfunción. Puede hacer referencia a él Microsoft.VisualBasic.dlly usarlo.

Shahkalpesh
fuente
¿Solo puede obtener ese método VB en versiones> 2.0 de .net?
Ed S.
@ChuckD: Eso es subjetivo. ¿Refiere bibliotecas externas que tratan con json o lo escribe todo para analizar json usted mismo?
shahkalpesh
@ChuckD: Ahórrame las tonterías y explica por qué es una mierda. Para mí, es solo otra dll que contiene algunas clases / funciones útiles.
shahkalpesh
@ChuckD Creo que no estás siendo razonable aquí. La función hace el trabajo, es fácil de importar y no es tan importante.
Errores
1
@ChuckD es posible que desee comenzar con una crítica constructiva en lugar de comenzar con Importing VisualBasic.dll for IsNumeric debería hacer que lo despidan. lo que claramente va a hacer que alguien vuelva. La respuesta fue en el '09 e incluso ahora es útil para algunas personas.
Bugs
4

Extensión simple:

public static bool IsNumeric(this String str)
{
    try
    {
        Double.Parse(str.ToString());
        return true;
    }
    catch {
    }
    return false;
}
MrSiir
fuente
si el parámetro de entrada es una cadena, ¿por qué usar .ToString ()?
technoman23
Sin embargo, esta respuesta es buena porque elimina la variable basura necesaria para el método TryParse, que se usa en respuestas como la solución de NER1808.
technoman23
3
public static bool IsNumeric(string anyString)
{
    if (anyString == null)
    {
        anyString = "";
    }

    if (anyString.Length > 0)
    {
        double dummyOut = new double();
        System.Globalization.CultureInfo cultureInfo = new System.Globalization.CultureInfo("en-US", true);
        return Double.TryParse(anyString, System.Globalization.NumberStyles.Any, cultureInfo.NumberFormat, out dummyOut);
    }
    else
    {
        return false;
    }
}
Mnaouar
fuente
3

Tal vez esta sea una característica de C # 3, pero podría usarla double.NaN.

Kenny
fuente
2

En realidad, Double.NaNes compatible con todas las versiones de .NET 2.0 y posteriores.

Gato malo
fuente
2

Estuve usando el fragmento de Chris Lively (respuesta seleccionada) encapsulado en una función bool como la sugerencia de Gishu durante un año o dos. Lo usé para asegurarme de que ciertas cadenas de consulta fueran solo numéricas antes de continuar con el procesamiento posterior. Comencé a recibir algunas cadenas de consulta erróneas que la respuesta marcada no manejaba, específicamente, cada vez que se pasaba una coma después de un número como "3645" (devuelto verdadero). Este es el mod resultante:

   static public bool IsNumeric(string s)
   {
      double myNum = 0;
      if (Double.TryParse(s, out myNum))
      {
         if (s.Contains(",")) return false;
         return true;
      }
      else
      {
         return false;
      }
   }
secreto
fuente
+1 por ser interesante. Supongo que es más una cuestión de uso. En otras palabras, si solo desea asegurarse de que el valor se pueda convertir a un número sin arrojar un error, entonces mi respuesta original es buena. Sin embargo, si le preocupa más que todos los caracteres dentro de la cadena sean en realidad dígitos, entonces se necesita un enfoque completamente diferente
NotMe
Double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out myNum)
Sam Harwell
0

Tengo una versión ligeramente diferente que devuelve el número. Supongo que en la mayoría de los casos, después de probar la cadena, querrá usar el número.

public bool IsNumeric(string numericString, out Double numericValue)
{
    if (Double.TryParse(numericString, out numericValue))
        return true;
    else
        return false;
}
Keith Aymar
fuente
0

Ésta es una versión modificada de la solución propuesta por el Sr. Siir. Encuentro que agregar un método de extensión es la mejor solución para la reutilización y la simplicidad en el método de llamada.

public static bool IsNumeric(this String s)
{
    try { double.Parse(s); return true; }
    catch (Exception) { return false; }
}

Modifiqué el cuerpo del método para que se ajustara a 2 líneas y eliminé la implementación innecesaria de .ToString (). Para aquellos que no están familiarizados con los métodos de extensión, aquí se explica cómo implementar:

Cree un archivo de clase llamado ExtensionMethods . Pega este código:

using System;
using System.Collections.Generic;
using System.Text;

namespace YourNameSpaceHere
{
    public static class ExtensionMethods
    {
        public static bool IsNumeric(this String s)
        {
            try { double.Parse(s); return true; }
            catch (Exception) { return false; }
        }
    }
}

Reemplace YourNameSpaceHere con su NameSpace real. Guardar cambios. Ahora puede usar el método de extensión en cualquier lugar de su aplicación:

bool validInput = stringVariable.IsNumeric();

Nota: este método devolverá verdadero para enteros y decimales, pero devolverá falso si la cadena contiene una coma. Si desea aceptar la entrada con comas o símbolos como "$", sugeriría implementar un método para eliminar esos caracteres primero y luego probar si IsNumeric.

technoman23
fuente