Jaki jest odpowiednik NaN lub IsNumeric w języku C #?

103

Jaki jest najbardziej efektywny sposób testowania ciągu wejściowego, niezależnie od tego, czy zawiera on wartość liczbową (lub odwrotnie, nie jest liczbą)? Myślę, że mogę użyć Double.Parsewyrażenia regularnego lub (patrz poniżej), ale zastanawiałem się, czy jest jakiś wbudowany sposób, aby to zrobić, na przykład javascript NaN()lub IsNumeric()( czy to VB, nie pamiętam?).

public static bool IsNumeric(this string value)
{
    return Regex.IsMatch(value, "^\\d+$");
}
johnc
źródło
1
Możliwy duplikat Jak mogę zidentyfikować, czy ciąg jest liczbą?
Michael Freidgeim

Odpowiedzi:

176

To nie ma narzutu wyrażenia regularnego

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

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

Nawiasem mówiąc, wszystkie standardowe typy danych, z rażącym wyjątkiem identyfikatorów GUID, obsługują TryParse.

update
secretwep podniósł, że wartość „2345” przejdzie powyższy test jako liczba. Jeśli jednak chcesz się upewnić, że wszystkie znaki w ciągu są cyframi, należy zastosować inne podejście.

Przykład 1 :

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

  return value;
}

lub jeśli chcesz być trochę bardziej fantazyjny

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

aktualizacja 2 (z @stackonfire, aby poradzić sobie z pustymi lub pustymi ciągami)

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; 
}
Nie ja
źródło
W razie potrzeby możesz zawinąć powyższy kod w bardziej przydatną metodę narzędzia, taką jak public static bool IsInteger (string sMaybeANumber)
Gishu
@Gishu: Masz rację, jeśli zależy Ci tylko na tym, czy liczba może zostać przekonwertowana.
NotMe
2
Jedynym problemem jest to, że Numberobiekt w JavaScript to liczba zmiennoprzecinkowa lub liczba całkowita, więc zmiana na double.TryParse byłaby dokładniejszym odpowiednikiem
Chris S
7
Możesz zachować ostrożność, ponieważ ciągi „NaN” i „Infinity” przetwarzają na a double, ale wielu uważa, że ​​nie są one numeryczne.
Mike Zboray
1
Poprawiony przykład 1, aby poradzić sobie z pustymi lub pustymi ciągami, które w przeciwnym razie powodowały, że IsNumber błędnie zwracał wartość 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; }
stackonfire
41

Wolę coś takiego, pozwala ci zdecydować, na co NumberStyleprzetestować.

public static Boolean IsNumeric(String input, NumberStyles numberStyle) {
    Double temp;
    Boolean result = Double.TryParse(input, numberStyle, CultureInfo.CurrentCulture, out temp);
    return result;
}
Anthony Mastrean
źródło
7
+1 za bycie jedyną jak dotąd osobą do Double.TryParse zamiast Int.TryParse :)
johnc
Jest to również, oczywiście, prawie metoda rozszerzenia.
Anthony Mastrean,
19

Oprócz poprzednich poprawnych odpowiedzi warto prawdopodobnie zwrócić uwagę, że „Not a Number” (NaN) w swoim ogólnym zastosowaniu nie jest równoważne z ciągiem znaków, którego nie można ocenić jako wartości liczbowej. NaN jest zwykle rozumiane jako wartość liczbowa używana do przedstawienia wyniku „niemożliwego” obliczenia - w przypadku gdy wynik jest nieokreślony. W związku z tym powiedziałbym, że użycie Javascript jest nieco mylące. W języku C # NaN jest zdefiniowane jako właściwość pojedynczych i podwójnych typów numerycznych i jest używane do wyraźnego odniesienia się do wyniku nurkowania zero przez zero. Inne języki używają go do reprezentowania różnych „niemożliwych” wartości.

Stu Mackellar
źródło
11

Wiem, że odpowiedzi udzielono na wiele różnych sposobów, z rozszerzeniami i przykładami lambda, ale kombinacją obu dla najprostszego rozwiązania.

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

lub jeśli używasz programu Visual Studio 2015 (C # 6,0 lub nowszego)

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

Niesamowity C # 6 w jednej linii. Oczywiście jest to ograniczone, ponieważ sprawdza tylko dla znaków numerycznych.

Aby użyć, wystarczy mieć ciąg znaków i wywołać na nim metodę, na przykład:

bool IsaNumber = "123456".IsNumeric();
Paul Bartlett
źródło
1
Dla użytkowników, którzy nie są zaznajomieni z metodami rozszerzającymi , korzystne może być dołączenie dodatkowych informacji (lub przynajmniej otaczającej klasy statycznej, aby zapewnić pełniejszy przykład).
johnnyRose
Nie podoba mi się to rozwiązanie, ponieważ zwróci fałsz dla liczb z ułamkiem dziesiętnym. Może to być przydatne w przypadku liczb całkowitych, ale jeśli tego chcesz użyć do metody, należy zmienić nazwę na IsInteger
technoman23
5

Tak, IsNumeric to VB. Zwykle ludzie używają metody TryParse (), chociaż jest ona nieco niezgrabna. Jak zasugerowałeś, zawsze możesz napisać własny.

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

}
Ed S.
źródło
5

Podoba mi się metoda rozszerzenia, ale nie lubię rzucać wyjątków, jeśli to możliwe. Zdecydowałem się na metodę rozszerzenia, biorąc tutaj najlepszą z 2 odpowiedzi.

    /// <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
źródło
4

Nadal możesz używać funkcji Visual Basic w języku C #. Jedyne, co musisz zrobić, to postępować zgodnie z poniższymi instrukcjami:

  1. Dodaj odwołanie do biblioteki Visual Basic, klikając prawym przyciskiem myszy projekt i wybierając opcję „Dodaj odwołanie”:

wprowadź opis obrazu tutaj

  1. Następnie zaimportuj go do swojej klasy, jak pokazano poniżej:

    przy użyciu Microsoft.VisualBasic;

  2. Następnie użyj go w dowolnym miejscu, jak pokazano poniżej:

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

Mam nadzieję, że to pomaga i powodzenia!

Vincy
źródło
2
Chociaż nie polecałbym tej metody, jest to poprawna odpowiedź. Nie jestem pewien, dlaczego głosowano w dół, a ponieważ nie wyjaśniono, dlaczego też, zagłosowałem za przeciwdziałaniem temu :-)
Abacus
4

VB ma IsNumericfunkcję. Możesz się odwołać Microsoft.VisualBasic.dlli użyć.

shahkalpesh
źródło
Czy możesz uzyskać tę metodę VB tylko w wersjach> 2.0 .net?
Ed S.
@ChuckD: To jest subiektywne. Czy polecasz zewnętrzne biblioteki, które zajmują się json, czy piszesz wszystko, aby samodzielnie przeanalizować json?
shahkalpesh,
@ChuckD: Oszczędź mi bzdur i wyjaśnij, dlaczego to bzdury. Dla mnie to tylko kolejna biblioteka dll, która zawiera kilka przydatnych klas / funkcji.
shahkalpesh,
@ChuckD Myślę, że jesteś tutaj nierozsądny. Funkcja spełnia swoje zadanie, jest łatwa do zaimportowania i nie jest taka wielka.
Błędy,
1
@ChuckD możesz zacząć od konstruktywnej krytyki zamiast zaczynać od Importowania VisualBasic.dll dla IsNumeric, powinno cię zwolnić! co najwyraźniej spowoduje, że ktoś wesprze. Odpowiedź pojawiła się w '09 i nawet teraz może być przydatna dla niektórych osób.
Błędy,
4

Proste rozszerzenie:

public static bool IsNumeric(this String str)
{
    try
    {
        Double.Parse(str.ToString());
        return true;
    }
    catch {
    }
    return false;
}
MrSiir
źródło
jeśli parametr wejściowy jest ciągiem, dlaczego używać .ToString ()?
technoman 23
Ta odpowiedź jest jednak dobra, ponieważ eliminuje zmienną śmieciową potrzebną dla metody TryParse, która jest używana w odpowiedziach takich jak rozwiązanie NER1808.
technoman 23
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
źródło
3

Może to jest funkcja C # 3, ale możesz użyć double.NaN.

Kenny
źródło
2

W rzeczywistości Double.NaNjest obsługiwany we wszystkich wersjach .NET 2.0 i nowszych.

Wściekły kot
źródło
2

Używałem fragmentu Chrisa Lively'ego (wybrana odpowiedź) zamkniętego w funkcji bool, takiej jak sugestia Gishu, przez rok lub dwa. Użyłem go, aby upewnić się, że niektóre ciągi zapytań są tylko numeryczne przed przystąpieniem do dalszego przetwarzania. Zacząłem otrzymywać błędne zapytania, których oznaczona odpowiedź nie obsługiwała, szczególnie za każdym razem, gdy przecinek został przekazany po liczbie takiej jak „3645” (zwrócona prawda). Oto wynikowy 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
źródło
+1 za bycie interesującym. Myślę, że jest to bardziej kwestia użytkowania. Innymi słowy, jeśli chcesz się tylko upewnić, że wartość można przekonwertować na liczbę bez zgłaszania błędu, moja pierwotna odpowiedź jest dobra. Jeśli jednak bardziej
martwisz się
Double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out myNum)
Sam Harwell
0

Mam nieco inną wersję, która zwraca liczbę. Domyślam się, że w większości przypadków po przetestowaniu ciągu chciałbyś użyć liczby.

public bool IsNumeric(string numericString, out Double numericValue)
{
    if (Double.TryParse(numericString, out numericValue))
        return true;
    else
        return false;
}
Keith Aymar
źródło
0

To zmodyfikowana wersja rozwiązania zaproponowanego przez pana Siira. Uważam, że dodanie metody rozszerzenia jest najlepszym rozwiązaniem do ponownego użycia i prostoty metody wywoływania.

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

Zmodyfikowałem treść metody, aby pasowała do 2 wierszy i usunąłem niepotrzebną implementację .ToString (). Dla tych, którzy nie są zaznajomieni z metodami rozszerzającymi, oto jak zaimplementować:

Utwórz plik klasy o nazwie ExtensionMethods . Wklej ten kod:

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

Zastąp YourNameSpaceHere rzeczywistą przestrzenią nazw. Zapisz zmiany. Teraz możesz korzystać z metody rozszerzenia w dowolnym miejscu aplikacji:

bool validInput = stringVariable.IsNumeric();

Uwaga: ta metoda zwróci wartość true dla liczb całkowitych i dziesiętnych, ale zwróci wartość false, jeśli ciąg zawiera przecinek. Jeśli chcesz akceptować dane wejściowe za pomocą przecinków lub symboli, takich jak „$”, sugerowałbym najpierw zaimplementowanie metody usuwania tych znaków, a następnie przetestowanie, czy IsNumeric.

technoman23
źródło