Was ist das C # -Äquivalent von NaN oder IsNumeric?

102

Was ist die effizienteste Methode, um eine Eingabezeichenfolge zu testen, ob sie einen numerischen Wert enthält (oder umgekehrt keine Zahl)? Ich denke, ich kann Double.Parseoder einen regulären Ausdruck verwenden (siehe unten), aber ich habe mich gefragt, ob es dafür eine eingebaute Methode gibt, wie Javascript NaN()oder IsNumeric()(war das VB, an das ich mich nicht erinnern kann?).

public static bool IsNumeric(this string value)
{
    return Regex.IsMatch(value, "^\\d+$");
}
Johnc
quelle
1
Mögliches Duplikat von Wie identifiziere ich, ob eine Zeichenfolge eine Zahl ist?
Michael Freidgeim

Antworten:

176

Dies hat keinen Regex-Overhead

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

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

Im Übrigen unterstützen alle Standarddatentypen, mit Ausnahme der GUIDs, TryParse.

update
secretwep hat darauf hingewiesen, dass der Wert "2345" den obigen Test als Zahl besteht. Wenn Sie jedoch sicherstellen müssen, dass alle Zeichen in der Zeichenfolge Ziffern sind, sollten Sie einen anderen Ansatz wählen.

Beispiel 1 :

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

  return value;
}

oder wenn du etwas ausgefallener sein willst

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

Update 2 (von @stackonfire, um mit null oder leeren Zeichenfolgen umzugehen)

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; 
}
Nicht ich
quelle
Bei Bedarf können Sie den obigen Code in eine hilfreichere Dienstprogrammmethode wie public static bool IsInteger (Zeichenfolge sMaybeANumber)
Gishu
@Gishu: Sie haben Recht, wenn Sie sich nur darum kümmern, ob die Zahl konvertiert werden kann.
NotMe
2
Das einzige Problem dabei ist, dass das NumberObjekt in Javascript ein Gleitkommawert oder eine Ganzzahl ist, sodass der Wechsel zu double.TryParse ein genaueres Äquivalent wäre
Chris S
7
Vielleicht möchten Sie damit vorsichtig sein, da die Zeichenfolgen "NaN" und "Infinity" zu a analysiert werden double, aber viele würden sie als nicht numerisch betrachten.
Mike Zboray
1
Ein korrigiertes Beispiel 1 für null oder leere Zeichenfolgen, die andernfalls dazu führten, dass IsNumber fälschlicherweise true 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; }
zurückgab
41

Ich bevorzuge so etwas, damit Sie entscheiden können, worauf Sie NumberStyletesten möchten .

public static Boolean IsNumeric(String input, NumberStyles numberStyle) {
    Double temp;
    Boolean result = Double.TryParse(input, numberStyle, CultureInfo.CurrentCulture, out temp);
    return result;
}
Anthony Mastrean
quelle
7
+1 für die einzige Person, die bisher Double.TryParse anstelle von Int.TryParse verwendet hat :)
Johnc
Dies ist natürlich auch fast eine Erweiterungsmethode.
Anthony Mastrean
19

Zusätzlich zu den vorherigen korrekten Antworten ist wahrscheinlich darauf hinzuweisen, dass "Not a Number" (NaN) in seiner allgemeinen Verwendung nicht einer Zeichenfolge entspricht, die nicht als numerischer Wert ausgewertet werden kann. NaN wird normalerweise als numerischer Wert verstanden, der verwendet wird, um das Ergebnis einer "unmöglichen" Berechnung darzustellen - wobei das Ergebnis undefiniert ist. In dieser Hinsicht würde ich sagen, dass die Verwendung von Javascript leicht irreführend ist. In C # ist NaN als eine Eigenschaft des einfachen und doppelten numerischen Typs definiert und wird verwendet, um explizit auf das Ergebnis des Tauchens von Null zu Null zu verweisen. Andere Sprachen verwenden es, um andere "unmögliche" Werte darzustellen.

Stu Mackellar
quelle
11

Ich weiß, dass dies auf viele verschiedene Arten beantwortet wurde, mit Erweiterungen und Lambda-Beispielen, aber eine Kombination aus beiden für die einfachste Lösung.

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

oder wenn Sie Visual Studio 2015 (C # 6.0 oder höher) verwenden

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

Geniales C # 6 in einer Zeile. Dies ist natürlich begrenzt, da nur numerische Zeichen geprüft werden.

Verwenden Sie zur Verwendung einfach eine Zeichenfolge und rufen Sie die Methode auf, z. B.:

bool IsaNumber = "123456".IsNumeric();
Paul Bartlett
quelle
1
Für Benutzer, die mit Erweiterungsmethoden nicht vertraut sind , kann es hilfreich sein, weitere Informationen anzugeben (oder zumindest die umgebende statische Klasse, um ein vollständigeres Beispiel bereitzustellen).
Johnny Rose
Ich mag diese Lösung nicht, weil sie für Zahlen mit einer Dezimalzahl false zurückgibt. Es könnte für ganze Zahlen nützlich sein, aber wenn Sie es für die Methode verwenden möchten, sollten Sie es
technoman23
5

Ja, IsNumeric ist VB. Normalerweise verwenden die Leute die TryParse () -Methode, obwohl sie etwas umständlich ist. Wie Sie vorgeschlagen haben, können Sie jederzeit Ihre eigenen schreiben.

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

}
Ed S.
quelle
5

Ich mag die Erweiterungsmethode, aber wenn möglich, mag ich es nicht, Ausnahmen auszulösen. Ich habe mich für eine Erweiterungsmethode entschieden, bei der das Beste aus 2 Antworten hier verwendet wird.

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

Sie können die Visual Basic-Funktion weiterhin in C # verwenden. Das einzige, was Sie tun müssen, ist einfach meinen Anweisungen unten zu folgen:

  1. Fügen Sie den Verweis zur Visual Basic-Bibliothek hinzu, indem Sie mit der rechten Maustaste auf Ihr Projekt klicken und "Verweis hinzufügen" auswählen:

Geben Sie hier die Bildbeschreibung ein

  1. Dann importiert es in der Klasse wie unten dargestellt:

    Verwenden von Microsoft.VisualBasic;

  2. Verwenden Sie es als Nächstes , wie unten gezeigt:

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

Hoffe, das hilft und viel Glück!

Vincy
quelle
2
Obwohl ich diese Methode nicht empfehlen würde, ist sie eine richtige Antwort. Ich bin mir nicht sicher, warum es herabgestimmt wurde, und da es auch nicht erklärt wurde, warum, habe ich dafür gestimmt, um dem entgegenzuwirken :-)
Abacus
4

VB hat die IsNumericFunktion. Sie können darauf verweisen Microsoft.VisualBasic.dllund es verwenden.

shahkalpesh
quelle
Können Sie diese VB-Methode nur in> 2.0-Versionen von .net erhalten?
Ed S.
@ChuckD: Das ist subjektiv. Verweisen Sie auf externe Bibliotheken, die sich mit json befassen, oder schreiben Sie alles, um json selbst zu analysieren?
Shahkalpesh
@ChuckD: Ersparen Sie mir den Trottel und erklären Sie, warum es Mist ist. Für mich ist es nur eine weitere DLL, die einige nützliche Klassen / Funktionen enthält.
Shahkalpesh
@ChuckD Ich denke du bist hier unvernünftig. Die Funktion erledigt den Job, ist einfach zu importieren und keine große Sache.
Bugs
1
@ChuckD Vielleicht möchten Sie mit konstruktiver Kritik beginnen, anstatt mit dem Importieren von VisualBasic.dll für IsNumeric zu beginnen. das wird eindeutig jemanden wieder auf die Beine stellen. Die Antwort war im Jahr '09 und scheint auch jetzt noch für einige Leute nützlich zu sein.
Bugs
4

Einfache Erweiterung:

public static bool IsNumeric(this String str)
{
    try
    {
        Double.Parse(str.ToString());
        return true;
    }
    catch {
    }
    return false;
}
MrSiir
quelle
Wenn der Eingabeparameter eine Zeichenfolge ist, warum sollten Sie .ToString () verwenden?
technoman23
Diese Antwort ist jedoch gut, da sie die für die TryParse-Methode erforderliche Junk-Variable eliminiert, die in Antworten wie der Lösung von NER1808 verwendet wird.
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
quelle
3

Vielleicht ist dies eine C # 3-Funktion, aber Sie könnten sie verwenden double.NaN.

kenny
quelle
2

Wird Double.NaNin allen .NET-Versionen 2.0 und höher unterstützt.

Verrückte Katze
quelle
2

Ich habe Chris Livelys Snippet (ausgewählte Antwort) für ein oder zwei Jahre in einer Bool-Funktion wie Gishus Vorschlag verwendet. Ich habe es verwendet, um sicherzustellen, dass bestimmte Abfragezeichenfolgen nur numerisch sind, bevor ich mit der weiteren Verarbeitung fortfahre. Ich bekam einige fehlerhafte Querringe, die von der markierten Antwort nicht verarbeitet wurden, insbesondere dann, wenn nach einer Zahl wie "3645" ein Komma übergeben wurde (true zurückgegeben). Dies ist der resultierende Mod:

   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;
      }
   }
secretwep
quelle
+1 für interessant zu sein. Ich denke, es ist eher eine Verwendungsfrage. Mit anderen Worten, wenn Sie nur sicherstellen möchten, dass der Wert ohne Fehler in eine Zahl umgewandelt werden kann, ist meine ursprüngliche Antwort gut. Wenn Sie jedoch mehr Bedenken haben, dass alle Zeichen in der Zeichenfolge tatsächlich Ziffern sind, ist ein völlig anderer Ansatz erforderlich
NotMe
Double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out myNum)
Sam Harwell
0

Ich habe eine etwas andere Version, die die Nummer zurückgibt. Ich würde vermuten, dass Sie in den meisten Fällen nach dem Testen der Zeichenfolge die Nummer verwenden möchten.

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

Dies ist eine modifizierte Version der von Herrn Siir vorgeschlagenen Lösung. Ich finde, dass das Hinzufügen einer Erweiterungsmethode die beste Lösung für die Wiederverwendung und Einfachheit der aufrufenden Methode ist.

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

Ich habe den Methodenkörper so geändert, dass er in zwei Zeilen passt, und die unnötige .ToString () - Implementierung entfernt. Für diejenigen, die mit Erweiterungsmethoden nicht vertraut sind, gilt Folgendes:

Erstellen Sie eine Klassendatei mit dem Namen ExtensionMethods . In diesen Code einfügen:

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

Ersetzen Sie YourNameSpaceHere durch Ihren tatsächlichen NameSpace. Änderungen speichern. Jetzt können Sie die Erweiterungsmethode überall in Ihrer App verwenden:

bool validInput = stringVariable.IsNumeric();

Hinweis: Diese Methode gibt true für Ganzzahlen und Dezimalstellen zurück, gibt jedoch false zurück, wenn die Zeichenfolge ein Komma enthält. Wenn Sie Eingaben mit Kommas oder Symbolen wie "$" akzeptieren möchten, würde ich empfehlen, zuerst eine Methode zu implementieren, um diese Zeichen zu entfernen, und dann zu testen, ob IsNumeric.

technoman23
quelle