C # เทียบเท่ากับ NaN หรือ IsNumeric คืออะไร?


103

วิธีใดเป็นวิธีที่มีประสิทธิภาพที่สุดในการทดสอบสตริงอินพุตว่ามีค่าตัวเลข (หรือตรงกันข้ามไม่ใช่ตัวเลข) ฉันเดาว่าฉันสามารถใช้Double.Parseหรือ regex ได้ (ดูด้านล่าง) แต่ฉันสงสัยว่ามีบางอย่างที่สร้างขึ้นเพื่อทำสิ่งนี้เช่น javascript NaN()หรือIsNumeric()(VB นั้นฉันจำไม่ได้หรือไม่)

public static bool IsNumeric(this string value)
{
    return Regex.IsMatch(value, "^\\d+$");
}

คำตอบ:


177

สิ่งนี้ไม่มีค่าโสหุ้ย 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
}

อนึ่งชนิดข้อมูลมาตรฐานทั้งหมดที่มีข้อยกเว้นที่เห็นได้ชัดของ GUID สนับสนุน TryParse

update
secretwep ขึ้นมาว่าค่า "2345" จะผ่านการทดสอบข้างต้นเป็นตัวเลข อย่างไรก็ตามหากคุณต้องการให้แน่ใจว่าอักขระทั้งหมดในสตริงเป็นตัวเลขคุณควรใช้วิธีอื่น

ตัวอย่างที่ 1 :

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

  return value;
}

หรือหากคุณต้องการเป็นแฟนซีมากขึ้น

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

อัปเดต 2 (จาก @stackonfire เพื่อจัดการกับสตริงว่างหรือว่าง)

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

หากจำเป็นคุณสามารถรวมโค้ดด้านบนเป็นวิธียูทิลิตี้ที่เป็นประโยชน์มากขึ้นเช่น IsInteger บูลแบบคงที่สาธารณะ (สตริง sMaybeANumber)
Gishu

@ Gishu: คุณพูดถูกถ้าสิ่งที่คุณสนใจคือตัวเลขสามารถแปลงได้หรือไม่
NotMe

2
ปัญหาเดียวของสิ่งนี้คือNumberวัตถุใน Javascript คือจำนวนทศนิยมหรือจำนวนเต็มดังนั้นการเปลี่ยนเป็นสองเท่า TryParse จะเทียบเท่าที่แน่นอนกว่า
Chris S

7
คุณอาจต้องระวังเรื่องนี้เนื่องจากสตริง "NaN" และ "Infinity" จะแยกวิเคราะห์เป็น a doubleแต่หลายคนคิดว่าค่าเหล่านี้ไม่ใช่ตัวเลข
Mike Zboray

1
ตัวอย่างที่ 1 ที่ได้รับการแก้ไขเพื่อจัดการกับสตริงว่างหรือว่างซึ่งทำให้ 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

ฉันชอบอะไรแบบนี้มันช่วยให้คุณตัดสินใจได้ว่าNumberStyleจะทดสอบอะไร

public static Boolean IsNumeric(String input, NumberStyles numberStyle) {
    Double temp;
    Boolean result = Double.TryParse(input, numberStyle, CultureInfo.CurrentCulture, out temp);
    return result;
}

7
+1 สำหรับการเป็นคนเดียวจนถึง Double.TryParse แทน Int.TryParse :)
johnc

นอกจากนี้ยังเห็นได้ชัดว่าเกือบจะเป็นวิธีการขยาย
Anthony Mastrean

19

นอกเหนือจากคำตอบที่ถูกต้องก่อนหน้านี้แล้วยังควรชี้ให้เห็นว่า "ไม่ใช่ตัวเลข" (NaN) ในการใช้งานทั่วไปไม่เทียบเท่ากับสตริงที่ไม่สามารถประเมินเป็นค่าตัวเลขได้ โดยปกติแล้ว NaN จะเข้าใจว่าเป็นค่าตัวเลขที่ใช้แทนผลลัพธ์ของการคำนวณ "เป็นไปไม่ได้" - โดยที่ผลลัพธ์ไม่ได้กำหนดไว้ ในแง่นี้ฉันจะบอกว่าการใช้งาน Javascript ทำให้เข้าใจผิดเล็กน้อย ใน C # NaN ถูกกำหนดให้เป็นคุณสมบัติของประเภทตัวเลขเดี่ยวและตัวเลขคู่และใช้เพื่ออ้างถึงผลลัพธ์ของการดำน้ำเป็นศูนย์โดยศูนย์อย่างชัดเจน ภาษาอื่นใช้เพื่อแสดงค่า "เป็นไปไม่ได้" ที่แตกต่างกัน


11

ฉันรู้ว่าสิ่งนี้ได้รับคำตอบในหลาย ๆ วิธีด้วยส่วนขยายและตัวอย่างแลมบ์ดา แต่การรวมกันของทั้งสองอย่างเพื่อวิธีแก้ปัญหาที่ง่ายที่สุด

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

หรือถ้าคุณใช้ Visual Studio 2015 (C # 6.0 ขึ้นไป) แล้ว

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

C # 6 ที่ยอดเยี่ยมในหนึ่งบรรทัด แน่นอนว่าสิ่งนี้มีข้อ จำกัด เนื่องจากเป็นการทดสอบเฉพาะอักขระตัวเลขเท่านั้น

ในการใช้งานเพียงแค่มีสตริงและเรียกใช้เมธอดเช่น:

bool IsaNumber = "123456".IsNumeric();

1
สำหรับผู้ใช้ที่ไม่คุ้นเคยกับวิธีการขยายอาจเป็นประโยชน์ในการใส่ข้อมูลเพิ่มเติม (หรืออย่างน้อยที่สุดก็คือคลาสคงที่โดยรอบเพื่อให้เป็นตัวอย่างที่สมบูรณ์ยิ่งขึ้น)
johnnyRose

ฉันไม่ชอบวิธีนี้เพราะมันจะส่งคืนค่าเท็จสำหรับตัวเลขที่มีทศนิยม มันอาจจะเป็นประโยชน์สำหรับจำนวนเต็ม แต่ถ้าว่าสิ่งที่คุณต้องการที่จะใช้สำหรับวิธีการที่ควรจะเปลี่ยนชื่อ IsInteger
technoman23

5

ใช่ IsNumeric คือ VB โดยปกติผู้คนมักใช้วิธี TryParse () แม้ว่ามันจะค่อนข้างเกะกะ ตามที่คุณแนะนำคุณสามารถเขียนของคุณเองได้ตลอดเวลา

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

}

5

ฉันชอบวิธีการขยาย แต่ไม่ชอบทิ้งข้อยกเว้นถ้าเป็นไปได้ ฉันเลือกใช้วิธีการขยายโดยใช้คำตอบที่ดีที่สุด 2 ข้อที่นี่

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

4

คุณยังสามารถใช้ฟังก์ชัน Visual Basic ใน C # ได้ สิ่งเดียวที่คุณต้องทำคือทำตามคำแนะนำของฉันที่แสดงด้านล่าง:

  1. เพิ่มการอ้างอิงไปยัง Visual Basic Libraryโดยคลิกขวาที่โครงการของคุณและเลือก "เพิ่มการอ้างอิง":

ป้อนคำอธิบายภาพที่นี่

  1. จากนั้นนำเข้าในชั้นเรียนของคุณดังที่แสดงด้านล่าง:

    ใช้ Microsoft.VisualBasic;

  2. ถัดไปใช้ทุกที่ที่คุณต้องการดังที่แสดงด้านล่าง:

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

หวังว่านี่จะช่วยและโชคดี!


2
แม้ว่าฉันจะไม่แนะนำวิธีนี้ แต่ก็เป็นคำตอบที่ถูกต้อง ไม่แน่ใจว่าเหตุใดจึงถูกลดคะแนนและเนื่องจากไม่มีการอธิบายว่าเหตุใดฉันจึงโหวตให้ต่อต้าน :-)
Abacus

4

VB มีIsNumericฟังก์ชัน คุณสามารถอ้างอิงMicrosoft.VisualBasic.dllและใช้งานได้


คุณสามารถรับวิธี VB นั้นในเวอร์ชัน> 2.0 ของ. net ได้หรือไม่?
Ed S.

@ChuckD: นั่นเป็นเรื่องส่วนตัว คุณอ้างถึงไลบรารีภายนอกที่จัดการกับ json หรือเขียนทั้งหมดเพื่อแยกวิเคราะห์ json ด้วยตัวคุณเอง?
shahkalpesh

@ChuckD: ช่วยฉันขับรถและอธิบายว่าทำไมมันถึงอึ สำหรับฉันมันเป็นเพียง dll อื่นที่มีคลาส / ฟังก์ชันที่มีประโยชน์
ชาห์คาลเปช

@ChuckD ฉันคิดว่าคุณไม่มีเหตุผลที่นี่ ฟังก์ชั่นนี้ใช้งานได้ง่ายนำเข้าและไม่ใช่เรื่องใหญ่
Bugs

1
@ChuckD คุณอาจต้องการเริ่มต้นด้วยการวิจารณ์เชิงสร้างสรรค์แทนที่จะเริ่มต้นด้วยการนำเข้า VisualBasic.dll สำหรับ IsNumeric คุณควรจะถูกไล่ออก! ซึ่งเห็นได้ชัดว่าจะได้รับบางคนสำรอง คำตอบกลับมาในปี '09 และถึงแม้ตอนนี้จะเป็นประโยชน์กับบางคน
Bugs

4

ส่วนขยายอย่างง่าย:

public static bool IsNumeric(this String str)
{
    try
    {
        Double.Parse(str.ToString());
        return true;
    }
    catch {
    }
    return false;
}

ถ้าพารามิเตอร์อินพุตเป็นสตริงทำไมต้องใช้. ToString ()?
technoman23

คำตอบนี้ดีแม้ว่ามันจะกำจัดตัวแปรขยะที่จำเป็นสำหรับเมธอด TryParse ซึ่งใช้ในคำตอบเช่นโซลูชันของ 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;
    }
}



2

ฉันใช้ตัวอย่างข้อมูลของ Chris Lively (คำตอบที่เลือก) ซึ่งรวมอยู่ในฟังก์ชันบูลเหมือนคำแนะนำของ Gishu เป็นเวลาหนึ่งหรือสองปี ฉันใช้มันเพื่อให้แน่ใจว่าสตริงการสืบค้นบางอย่างเป็นตัวเลขเท่านั้นก่อนที่จะดำเนินการประมวลผลต่อไป ฉันเริ่มได้รับสตริงการสืบค้นที่ผิดพลาดซึ่งคำตอบที่ทำเครื่องหมายไว้ไม่ได้รับการจัดการโดยเฉพาะเมื่อใดก็ตามที่มีการส่งลูกน้ำตามหลังตัวเลขเช่น "3645" (ส่งกลับจริง) นี่คือผล 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;
      }
   }

+1 เพื่อความน่าสนใจ ฉันเดาว่ามันเป็นคำถามการใช้งานมากกว่า กล่าวอีกนัยหนึ่งถ้าคุณแค่ต้องการให้แน่ใจว่าสามารถแปลงค่าเป็นตัวเลขได้โดยไม่เกิดข้อผิดพลาดคำตอบเดิมของฉันก็ใช้ได้ดี อย่างไรก็ตามหากคุณกังวลมากขึ้นว่าอักขระทั้งหมดในสตริงเป็นตัวเลขจริง ๆ แล้วจำเป็นต้องใช้วิธีการที่แตกต่างไปจากเดิมอย่างสิ้นเชิง
NotMe

Double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out myNum)
Sam Harwell

0

ฉันมีเวอร์ชันที่แตกต่างกันเล็กน้อยซึ่งส่งคืนหมายเลข ฉันเดาว่าในกรณีส่วนใหญ่หลังจากทดสอบสตริงแล้วคุณจะต้องการใช้หมายเลข

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

0

นี่คือเวอร์ชันแก้ไขของโซลูชันที่เสนอโดย Mr Siir ฉันพบว่าการเพิ่มวิธีการขยายเป็นทางออกที่ดีที่สุดสำหรับการใช้ซ้ำและความเรียบง่ายในวิธีการโทร

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

ฉันแก้ไขเนื้อหาของวิธีการให้พอดีกับ 2 บรรทัดและลบการใช้งาน. ToString () ที่ไม่จำเป็น สำหรับผู้ที่ไม่คุ้นเคยกับวิธีการขยายนี่คือวิธีการใช้งาน:

สร้างไฟล์ชั้นเรียกว่าExtensionMethods วางรหัสนี้:

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

แทนที่YourNameSpaceHereด้วยNameSpaceจริงของคุณ บันทึกการเปลี่ยนแปลง. ตอนนี้คุณสามารถใช้วิธีการขยายได้ทุกที่ในแอปของคุณ:

bool validInput = stringVariable.IsNumeric();

หมายเหตุ: วิธีนี้จะคืนค่าจริงสำหรับจำนวนเต็มและทศนิยม แต่จะส่งกลับเท็จหากสตริงมีเครื่องหมายจุลภาค หากคุณต้องการยอมรับการป้อนข้อมูลด้วยลูกน้ำหรือสัญลักษณ์เช่น "$" ฉันขอแนะนำให้ใช้วิธีการลบอักขระเหล่านั้นก่อนจากนั้นทดสอบว่า IsNumeric

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.