Qual é o equivalente em C # de NaN ou IsNumeric?

103

Qual é a maneira mais eficiente de testar uma string de entrada se ela contém um valor numérico (ou, inversamente, Não é um número)? Eu acho que posso usar Double.Parseou um regex (veja abaixo), mas eu queria saber se existe alguma forma embutida de fazer isso, como javascript NaN()ou IsNumeric()(era VB, não me lembro?).

public static bool IsNumeric(this string value)
{
    return Regex.IsMatch(value, "^\\d+$");
}
johnc
fonte
1
Possível duplicata de Como identifico se uma string é um número?
Michael Freidgeim

Respostas:

176

Isso não tem sobrecarga de regex

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

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

A propósito, todos os tipos de dados padrão, com a notável exceção de GUIDs, oferecem suporte a TryParse.

update
secretwep mostrou que o valor "2345" passará no teste acima como um número. No entanto, se você precisar garantir que todos os caracteres na string sejam dígitos, outra abordagem deve ser adotada.

exemplo 1 :

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

  return value;
}

ou se você quer ser um pouco mais chique

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

atualização 2 (de @stackonfire para lidar com strings nulas ou vazias)

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; 
}
Eu não
fonte
Se necessário, você pode agrupar o código acima em um método utilitário mais útil, como public static bool IsInteger (string sMaybeANumber)
Gishu
@ Gishu: Você está certo se tudo o que importa é se o número pode ser convertido.
NotMe de
2
O único problema com isso é que o Numberobjeto em Javascript é um número flutuante ou inteiro, portanto, mudar para double. TryParse seria um equivalente mais exato
Chris S
7
Você pode querer ter cuidado com isso, pois as cadeias de caracteres "NaN" e "Infinity" são convertidas em a double, mas muitos as consideram não numéricas.
Mike Zboray
1
Um Exemplo 1 corrigido para lidar com strings nulas ou vazias, que de outra forma estavam fazendo com que IsNumber retornasse erroneamente verdadeiro: 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

Eu prefiro algo assim, permite que você decida o NumberStyleque testar.

public static Boolean IsNumeric(String input, NumberStyles numberStyle) {
    Double temp;
    Boolean result = Double.TryParse(input, numberStyle, CultureInfo.CurrentCulture, out temp);
    return result;
}
Anthony Mastrean
fonte
7
+1 por ser a única pessoa até agora a Double
TryParse em
Este também é, obviamente, quase um método de extensão.
Anthony Mastrean
19

Além das respostas corretas anteriores, provavelmente vale a pena apontar que "Not a Number" (NaN) em seu uso geral não é equivalente a uma string que não pode ser avaliada como um valor numérico. NaN é geralmente entendido como um valor numérico usado para representar o resultado de um cálculo "impossível" - onde o resultado é indefinido. A este respeito, eu diria que o uso de Javascript é um pouco enganador. Em C # NaN é definido como uma propriedade dos tipos numéricos simples e duplos e é usado para se referir explicitamente ao resultado do mergulho zero a zero. Outras linguagens o usam para representar diferentes valores "impossíveis".

Stu Mackellar
fonte
11

Eu sei que isso foi respondido de muitas maneiras diferentes, com extensões e exemplos lambda, mas uma combinação de ambos para a solução mais simples.

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

ou se você estiver usando o Visual Studio 2015 (C # 6.0 ou superior),

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

Excelente C # 6 em uma linha. É claro que isso é limitado porque testa apenas caracteres numéricos.

Para usar, basta ter uma string e chamar o método nela, como:

bool IsaNumber = "123456".IsNumeric();
Paul Bartlett
fonte
1
Para usuários não familiarizados com os métodos de extensão , pode ser benéfico incluir mais algumas informações (ou pelo menos a classe estática circundante para fornecer um exemplo mais completo).
johnnyRose
Não gosto dessa solução porque ela retornará falso para números com decimal. Poderia ser útil para números inteiros, mas se é isso que você quer usá-lo para o método deve ser renomeado IsInteger
technoman23
5

Sim, IsNumeric é VB. Normalmente as pessoas usam o método TryParse (), embora seja um pouco desajeitado. Como você sugeriu, você sempre pode escrever o seu próprio.

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

}
Ed S.
fonte
5

Eu gosto do método de extensão, mas não gosto de lançar exceções, se possível. Optei por um método de extensão obtendo a melhor de 2 respostas aqui.

    /// <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
fonte
4

Você ainda pode usar a função Visual Basic em C #. A única coisa que você precisa fazer é apenas seguir minhas instruções mostradas abaixo:

  1. Adicione a referência à Biblioteca do Visual Basic clicando com o botão direito do mouse em seu projeto e selecionando "Adicionar Referência":

insira a descrição da imagem aqui

  1. Em seguida, importe -o em sua classe, conforme mostrado abaixo:

    using Microsoft.VisualBasic;

  2. Em seguida, use-o onde quiser, conforme mostrado abaixo:

                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 isso ajude e boa sorte!

Vincy
fonte
2
Embora eu não recomende esse método, é uma resposta correta. Não tenho certeza por que foi rejeitado, e como também não foi explicado por que, votei a favor para contra-atacar :-)
Abacus
4

O VB tem a IsNumericfunção. Você pode fazer referência Microsoft.VisualBasic.dlle usá-lo.

Shahkalpesh
fonte
Você só pode obter esse método VB em versões> 2.0 do .net?
Ed S.
@ChuckD: Isso é subjetivo. Você consulta bibliotecas externas que lidam com json ou escreve tudo para analisar json você mesmo?
shahkalpesh
@ChuckD: Poupe-me da baboseira e explique por que é uma porcaria. Para mim, é apenas mais uma dll que contém algumas classes / funções úteis.
shahkalpesh
@ChuckD Acho que você está sendo irracional aqui. A função faz o trabalho, é fácil de importar e não é um grande negócio.
Bugs
1
@ChuckD você pode querer começar com uma crítica construtiva em vez de começar com Importar VisualBasic.dll para IsNumeric deve fazer você ser despedido! o que claramente vai trazer alguém de volta. A resposta estava em 2009 e ainda hoje pode ser útil para algumas pessoas.
Bugs
4

Extensão simples:

public static bool IsNumeric(this String str)
{
    try
    {
        Double.Parse(str.ToString());
        return true;
    }
    catch {
    }
    return false;
}
MrSiir
fonte
se o parâmetro de entrada for uma string, por que usar .ToString ()?
technoman23
Essa resposta é boa porque elimina a variável lixo necessária para o método TryParse, que é usado em respostas como a solução 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
fonte
3

Talvez seja um recurso do C # 3, mas você pode usar double.NaN.

Kenny
fonte
2

Na verdade, Double.NaNé compatível com todas as versões do .NET 2.0 e superiores.

Gato louco
fonte
2

Eu estava usando o snippet (resposta selecionada) de Chris Lively encapsulado em uma função bool como a sugestão de Gishu por um ou dois anos. Usei-o para ter certeza de que certas strings de consulta eram apenas numéricas antes de prosseguir com o processamento. Comecei a receber algumas strings de consulta erradas que a resposta marcada não estava manipulando, especificamente, sempre que uma vírgula era passada após um número como "3645" (retornado verdadeiro). Este é o 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;
      }
   }
segredo
fonte
1 por ser interessante. Acho que é mais uma questão de uso. Em outras palavras, se você apenas deseja ter certeza de que o valor pode ser convertido em um número sem gerar um erro, minha resposta original é boa. No entanto, se você estiver mais preocupado que todos os caracteres dentro da string sejam na verdade dígitos, então uma abordagem completamente diferente é necessária
NotMe
Double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out myNum)
Sam Harwell
0

Tenho uma versão ligeiramente diferente que retorna o número. Eu acho que na maioria dos casos, depois de testar a string, você gostaria de usar o número.

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

Esta é uma versão modificada da solução proposta pelo Sr. Siir. Acho que adicionar um método de extensão é a melhor solução para reutilização e simplicidade no método de chamada.

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

Modifiquei o corpo do método para caber em 2 linhas e removi a implementação desnecessária de .ToString (). Para quem não está familiarizado com os métodos de extensão, aqui está como implementar:

Crie um arquivo de classe chamado ExtensionMethods . Cole neste 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; }
        }
    }
}

Substitua YourNameSpaceHere pelo seu NameSpace real. Salve as alterações. Agora você pode usar o método de extensão em qualquer lugar do seu aplicativo:

bool validInput = stringVariable.IsNumeric();

Observação: este método retornará verdadeiro para inteiros e decimais, mas retornará falso se a string contiver uma vírgula. Se você quiser aceitar a entrada com vírgulas ou símbolos como "$", sugiro implementar um método para remover esses caracteres primeiro e depois testar se IsNumeric.

technoman23
fonte