Quel est l'équivalent C # de NaN ou IsNumeric?

103

Quelle est la manière la plus efficace de tester une chaîne d'entrée si elle contient une valeur numérique (ou inversement Pas un nombre)? Je suppose que je peux utiliser Double.Parseou un regex (voir ci-dessous) mais je me demandais s'il y avait un moyen intégré pour le faire, comme javascript NaN()ou IsNumeric()(était-ce VB, je ne me souviens pas?).

public static bool IsNumeric(this string value)
{
    return Regex.IsMatch(value, "^\\d+$");
}
johnc
la source
1
Double possible de Comment identifier si une chaîne est un nombre?
Michael Freidgeim

Réponses:

176

Cela n'a pas la surcharge 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
}

Incidemment, tous les types de données standard, à l'exception flagrante des GUID, prennent en charge TryParse.

update
secretwep a indiqué que la valeur "2345" passera le test ci-dessus en tant que nombre. Cependant, si vous devez vous assurer que tous les caractères de la chaîne sont des chiffres, une autre approche doit être adoptée.

exemple 1 :

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

  return value;
}

ou si tu veux être un peu plus chic

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

mise à jour 2 (de @stackonfire pour traiter des chaînes nulles ou vides)

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; 
}
Pas moi
la source
Si nécessaire, vous pouvez envelopper le code ci-dessus dans une méthode utilitaire plus utile telle que public static bool IsInteger (string sMaybeANumber)
Gishu
@Gishu: Vous avez raison si vous vous souciez uniquement de savoir si le nombre peut être converti.
NotMe
2
Le seul problème avec ceci est que l' Numberobjet en Javascript est un flottant ou un entier, donc passer à double.TryParse serait un équivalent plus exact
Chris S
7
Vous voudrez peut-être être prudent avec cela car les chaînes "NaN" et "Infinity" sont analysées en a double, mais beaucoup les considéreraient comme n'étant pas numériques.
Mike Zboray
1
Un exemple 1 corrigé pour traiter les chaînes nulles ou vides, qui autrement provoquaient le renvoi erroné de IsNumber: 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

Je préfère quelque chose comme ça, cela vous permet de décider quoi NumberStyletester.

public static Boolean IsNumeric(String input, NumberStyles numberStyle) {
    Double temp;
    Boolean result = Double.TryParse(input, numberStyle, CultureInfo.CurrentCulture, out temp);
    return result;
}
Anthony Mastrean
la source
7
+1 pour avoir été la seule personne à ce jour à Double.TryParse au lieu de Int.TryParse :)
johnc
C'est aussi, évidemment, presque une méthode d'extension.
Anthony Mastrean
19

En plus des réponses correctes précédentes, il vaut probablement la peine de souligner que "Pas un nombre" (NaN) dans son usage général n'est pas équivalent à une chaîne qui ne peut pas être évaluée comme une valeur numérique. NaN est généralement compris comme une valeur numérique utilisée pour représenter le résultat d'un calcul "impossible" - où le résultat n'est pas défini. À cet égard, je dirais que l'utilisation de Javascript est légèrement trompeuse. En C #, NaN est défini comme une propriété des types numériques simple et double et est utilisé pour faire explicitement référence au résultat de la plongée zéro par zéro. D'autres langues l'utilisent pour représenter différentes valeurs "impossibles".

Stu Mackellar
la source
11

Je sais que cela a été répondu de nombreuses manières différentes, avec des extensions et des exemples lambda, mais une combinaison des deux pour la solution la plus simple.

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

ou si vous utilisez Visual Studio 2015 (C # 6.0 ou supérieur), alors

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

Génial C # 6 sur une seule ligne. Bien sûr, cela est limité car il ne teste que les caractères numériques.

Pour l'utiliser, il suffit d'avoir une chaîne et d'appeler la méthode dessus, telle que:

bool IsaNumber = "123456".IsNumeric();
Paul Bartlett
la source
1
Pour les utilisateurs peu familiarisés avec les méthodes d'extension , il peut être avantageux d'inclure des informations supplémentaires (ou au moins la classe statique environnante pour fournir un exemple plus complet).
johnnyRose
Je n'aime pas cette solution car elle retournera false pour les nombres avec une décimale. Cela pourrait être utile pour les entiers, mais si c'est ce que vous voulez l'utiliser, la méthode doit être renommée IsInteger
technoman23
5

Ouais, IsNumeric est VB. Habituellement, les gens utilisent la méthode TryParse (), bien qu'elle soit un peu maladroite. Comme vous l'avez suggéré, vous pouvez toujours écrire le vôtre.

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

}
Ed S.
la source
5

J'aime la méthode d'extension, mais je n'aime pas lancer des exceptions si possible. J'ai opté pour une méthode d'extension prenant le meilleur des 2 réponses ici.

    /// <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
la source
4

Vous pouvez toujours utiliser la fonction Visual Basic en C #. La seule chose que vous devez faire est simplement de suivre mes instructions ci-dessous:

  1. Ajoutez la référence à la bibliothèque Visual Basic en cliquant avec le bouton droit sur votre projet et en sélectionnant «Ajouter une référence»:

entrez la description de l'image ici

  1. Puis importez- le dans votre classe comme indiqué ci-dessous:

    en utilisant Microsoft.VisualBasic;

  2. Ensuite, utilisez-le où vous le souhaitez, comme indiqué ci-dessous:

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

J'espère que ça t'aide et bonne chance!

Vincy
la source
2
Bien que je ne recommanderais pas cette méthode, il est une réponse correcte. Je ne sais pas pourquoi il a été refusé, et comme il n'a pas été expliqué pourquoi non plus, j'ai voté pour le contrer :-)
Abacus
4

VB a la IsNumericfonction. Vous pouvez le référencer Microsoft.VisualBasic.dllet l'utiliser.

shahkalpesh
la source
Pouvez-vous obtenir cette méthode VB uniquement dans les versions> 2.0 de .net?
Ed S.
@ChuckD: C'est subjectif. Faites-vous référence à des bibliothèques externes qui traitent de json ou écrivez-vous tout pour analyser json vous-même?
shahkalpesh
@ChuckD: Epargnez-moi la bêtise et expliquez pourquoi c'est de la merde. Pour moi, c'est juste une autre dll qui contient des classes / fonctions utiles.
shahkalpesh
@ChuckD Je pense que vous êtes déraisonnable ici. La fonction fait le travail, elle est facile à importer et ce n'est pas si grave.
Bugs le
1
@ChuckD vous voudrez peut-être commencer par des critiques constructives au lieu de commencer par Importer VisualBasic.dll pour IsNumeric devrait vous faire virer! ce qui va clairement faire reculer quelqu'un. La réponse était de retour en '09 et peut même aujourd'hui être utile à certaines personnes.
Bugs
4

Extension simple:

public static bool IsNumeric(this String str)
{
    try
    {
        Double.Parse(str.ToString());
        return true;
    }
    catch {
    }
    return false;
}
MrSiir
la source
si le paramètre d'entrée est une chaîne, pourquoi utiliser .ToString ()?
technoman23
Cette réponse est bonne car elle élimine la variable indésirable nécessaire à la méthode TryParse, qui est utilisée dans des réponses comme la solution 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
la source
3

C'est peut-être une fonctionnalité C # 3, mais vous pouvez utiliser double.NaN.

Kenny
la source
2

En fait, Double.NaNest pris en charge dans toutes les versions .NET 2.0 et supérieures.

Chat fou
la source
2

J'utilisais l'extrait de Chris Lively (réponse sélectionnée) encapsulé dans une fonction booléenne comme la suggestion de Gishu pendant un an ou deux. Je l'ai utilisé pour m'assurer que certaines chaînes de requête n'étaient que numériques avant de poursuivre le traitement. J'ai commencé à avoir des chaînes de requêtes errantes que la réponse marquée ne traitait pas, en particulier, chaque fois qu'une virgule était passée après un nombre comme "3645", (renvoyé vrai). Voici le mod résultant:

   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;
      }
   }
secret
la source
+1 pour être intéressant. Je suppose que c'est plus une question d'utilisation. En d'autres termes, si vous voulez simplement vous assurer que la valeur peut être convertie en un nombre sans générer d'erreur, ma réponse originale est bonne. Cependant, si vous êtes plus préoccupé par le fait que tous les caractères de la chaîne sont en fait des chiffres, une approche complètement différente est nécessaire
NotMe
Double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out myNum)
Sam Harwell
0

J'ai une version légèrement différente qui renvoie le numéro. Je suppose que dans la plupart des cas, après avoir testé la chaîne, vous voudrez utiliser le nombre.

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

Il s'agit d'une version modifiée de la solution proposée par M. Siir. Je trouve que l'ajout d'une méthode d'extension est la meilleure solution pour la réutilisation et la simplicité dans la méthode d'appel.

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

J'ai modifié le corps de la méthode pour qu'il tienne sur 2 lignes et j'ai supprimé l'implémentation inutile .ToString (). Pour ceux qui ne sont pas familiarisés avec les méthodes d'extension, voici comment implémenter:

Créez un fichier de classe appelé ExtensionMethods . Collez ce code:

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; }
        }
    }
}

Remplacez YourNameSpaceHere par votre NameSpace réel. Sauvegarder les modifications. Vous pouvez maintenant utiliser la méthode d'extension n'importe où dans votre application:

bool validInput = stringVariable.IsNumeric();

Remarque: cette méthode retournera vrai pour les entiers et les décimales, mais retournera faux si la chaîne contient une virgule. Si vous voulez accepter l'entrée avec des virgules ou des symboles comme "$", je suggérerais d'implémenter une méthode pour supprimer ces caractères d'abord, puis de tester si IsNumeric.

technoman23
la source