วิธีการตรวจสอบว่าสตริงเป็นตัวเลขใน Java


886

คุณจะตรวจสอบว่า String เป็นตัวเลขก่อนที่จะแยกวิเคราะห์ได้อย่างไร


36
วิธีแก้ปัญหาทั้งหมดที่เสนอด้วยการแสดงออกปกติจะไม่ทำงานสำหรับเลขฐานสิบหก
Oscar Castiblanco

และส่งผ่านสตริง null ในการแข่งขัน (... ) ฟังก์ชั่นจะโยนข้อยกเว้น NullPointer
Hitesh Sahu

ดูคำตอบของ Max Malysh สำหรับวิธีแก้ปัญหา Java 8 ที่รัดกุมโดยไม่มีไลบรารีของ บริษัท อื่น
Andy Thomas

@HiteshSahu สตริง null ดูเหมือนว่าจะได้รับการจัดการอย่างสง่างามในเวอร์ชันล่าสุด (รวมถึง Java 6.x และ 7.x)
lifebalance

การแก้ปัญหาทั้งหมดเสนอให้ใช้จะไม่สามารถแยกหมายเลขโทรศัพท์มือถือด้วยInteger.parseInt() NumberFormatException
ไม่ใช่ข้อผิดพลาด

คำตอบ:


691

ด้วยApache คอมมอนส์แลง 3.5 ขึ้นไป: หรือNumberUtils.isCreatableStringUtils.isNumeric

ด้วยApache คอมมอนส์แลง 3.4 และด้านล่าง: หรือNumberUtils.isNumberStringUtils.isNumeric

นอกจากนี้คุณยังสามารถใช้StringUtils.isNumericSpaceที่ส่งกลับtrueสำหรับสตริงว่างและละเว้นช่องว่างภายในในสตริง อีกวิธีหนึ่งคือการใช้NumberUtils.isParsableซึ่งโดยทั่วไปตรวจสอบหมายเลขจะแยกวิเคราะห์ตาม Java (javadocs ที่เชื่อมโยงมีตัวอย่างโดยละเอียดสำหรับแต่ละวิธี)


59
StringUtils.isNumeric()อาจจะไม่เหมาะสมที่นี่เพราะมันจะตรวจสอบเพียงว่าสตริงเป็นลำดับของตัวเลข จะดีสำหรับ ints มากที่สุด แต่ไม่ได้สำหรับตัวเลขที่มีทศนิยมแยกกลุ่ม ฯลฯ
เจฟฟ์ Mercado

42
บูรณาการวงล้อเพราะคุณไม่ได้รวมไลบรารีทั้งหมดเพราะคุณต้องการฟังก์ชัน 3 บรรทัดในที่เดียว
dalvarezmartinez1

12
มันคุ้มที่จะเพิ่มทั้งไลบรารี่สำหรับฟีเจอร์นี้หรือไม่? เห็นได้ชัดว่าถ้ามันใช้กับสิ่งอื่น ๆ ที่ยอดเยี่ยม แต่ก็อาจจะเกินกำลังเพราะผู้คนได้แก้ไขมันในหนึ่งบรรทัดของรหัส
น้ำ

7
ไม่ทำงานกับเนกาทีฟ และครึ่งหนึ่งของตัวเลขทั้งหมดเป็นค่าลบดังนั้น .....
Paul Draper

6
@ PaulDraper: คุณพูดถูกStringUtilsไม่สนับสนุนสัญญาณนำ แต่คุณควรตรวจสอบNumberUtils.isCreatableมันรองรับเนกาทีฟอย่างถูกต้อง
palacsint

904

โดยทั่วไปจะทำด้วยฟังก์ชั่นที่ผู้ใช้กำหนดเอง (เช่นฟังก์ชั่น Roll ของคุณเอง "isNumeric")

สิ่งที่ต้องการ:

public static boolean isNumeric(String str) { 
  try {  
    Double.parseDouble(str);  
    return true;
  } catch(NumberFormatException e){  
    return false;  
  }  
}

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

วิธีอื่นอาจใช้นิพจน์ทั่วไปเพื่อตรวจสอบความถูกต้องของการเป็นตัวเลข:

public static boolean isNumeric(String str) {
  return str.matches("-?\\d+(\\.\\d+)?");  //match a number with optional '-' and decimal.
}

ระวังด้วยกลไก RegEx ข้างต้นเพราะจะล้มเหลวหากคุณใช้ตัวเลขที่ไม่ใช่ภาษาอาหรับ (เช่นตัวเลขอื่นที่ไม่ใช่ 0 ถึง 9) นี่เป็นเพราะส่วน "\ d" ของ RegEx จะจับคู่ [0-9] เท่านั้นและมีประสิทธิภาพไม่ทราบตัวเลขระหว่างประเทศ (ขอบคุณ OregonGhost ที่ชี้ให้เห็น!)

หรือแม้กระทั่งทางเลือกอื่นคือการใช้วัตถุ java.text.NumberFormat ในตัวของ Java เพื่อดูว่าหลังจากการแยกสตริงแล้วตำแหน่งตัวแยกวิเคราะห์จะอยู่ที่ส่วนท้ายของสตริง หากเป็นเช่นนั้นเราสามารถสันนิษฐานได้ว่าสตริงทั้งหมดเป็นตัวเลข:

public static boolean isNumeric(String str) {
  NumberFormat formatter = NumberFormat.getInstance();
  ParsePosition pos = new ParsePosition(0);
  formatter.parse(str, pos);
  return str.length() == pos.getIndex();
}

7
\ d ใน Java Regex ตรงกับตัวเลขละตินเท่านั้นหรือไม่ หากเป็นเช่น. NET regexes คุณจะพบปัญหากับตัวเลขอื่น ๆ (เช่นภาษาอาหรับ) ตามที่อธิบายไว้ที่นี่: blogs.msdn.com/oldnewthing/archive/2004/03/09/86555.aspx
OregonGhost

3
โซลูชัน numberFormatter อาจจะดีกว่าการจับ NumberFormatException เพียงเล็กน้อยเท่านั้น ฉันสงสัยว่าวิธีที่ดีที่สุดคือการใช้ regex
Chii

11
โปรดทราบว่า.ใน regex ของคุณจะตรงกับตัวละครใด ๆ ไม่เพียง แต่ตัวแยกทศนิยม
jqno

9
+1 สำหรับการรับรู้ค่าใช้จ่ายของการลอง / จับ นี่เป็นวิธีที่น่ากลัวที่จะใช้ในระยะยาวสำหรับการใช้งานซ้ำ ๆ แต่จริงๆแล้วเราติดอยู่กับที่ใน Java
demongolem

5
โปรดทราบว่าไม่มีสิ่งเช่น "เลขละติน" และตัวเลข 0-9 เป็นตัวเลขอารบิคจริง ผู้คนอาจคุ้นเคยกับตัวเลขโรมันซึ่งใช้โดยคนที่พูดภาษาละตินในรูปแบบ I, II, III, IV, V, VI และอื่น ๆen.wikipedia.org/wiki/Arabic_numerals ; en.wikipedia.org/wiki/Roman_numerals
dantiston

152

หากคุณใช้ Android คุณควรใช้:

android.text.TextUtils.isDigitsOnly(CharSequence str)

เอกสารสามารถพบได้ที่นี่

ให้มันง่าย ส่วนใหญ่ทุกคนสามารถ "re-program" (สิ่งเดียวกัน)


4
@ kape123 :) แน่ใจว่า "123.456" ไม่มีตัวเลข
Ahmed Alejo

8
หมายเหตุ: ผลลัพธ์นี้เป็น NPE สำหรับอินพุตว่าง นอกจากนี้จะไม่ทำงานกับตัวเลขหรือทศนิยม
gMale

2
ฉันชอบมัน!! ฉันคิดว่านี่เป็นเพียงตัวเลขเท่านั้น ไม่ได้สำหรับ.,-
illusionJJ

นี่คือสิ่งที่ฉันกำลังมองหา สิ่งที่ง่ายต่อการตรวจสอบเฉพาะตัวเลข 0-9 ฉันตั้งค่าตัวกรองในการประกาศ EditText ของฉัน แต่ในกรณีที่การเปลี่ยนแปลงหรือแทนที่ลงบนถนนก็ดีที่มีการตรวจสอบแบบโปรแกรมอย่างง่ายเช่นกัน
jwehrle

127

นิพจน์แลมบ์ดา Java 8

String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );

4
คุณสามารถใช้การอ้างอิงเมธอดได้เช่น: someString.chars (). allMatch (ตัวละคร :: isDigit)
Wienczny

3
เยี่ยมมาก แต่ก็ยังสามารถปรับแก้วงล้อได้เหมือน "วิธีแก้ปัญหา" เกือบทั้งหมดที่นี่ นอกจากนี้ล้มเหลวใน 'โมฆะ' (เกือบทั้งหมดอื่น ๆ )
qben

8
คำตอบนี้สั้นกระชับง่ายและอ่านได้ คุณเกือบจะสามารถอ่านได้เหมือนภาษาอังกฤษ - "ตัวอักษรทุกตัวที่ตรงกันทุกตัว" มันไม่จำเป็นต้องมีห้องสมุดบุคคลที่สาม มันไม่ได้ใช้ข้อยกเว้นในกรณีที่ไม่พิเศษ นี่ควรเป็นคำตอบที่ยอมรับได้
Andy Thomas

14
มันจะผลิตอะไรสำหรับ "-1"?
BalázsNémeth

2
ไม่ใช่คำตอบที่ถูก สตริงตัวเลขสามารถมีอักขระที่ไม่ใช่ตัวเลข (เช่น "." หรือ "-") และยังคงเป็นตัวเลขได้อย่างสมบูรณ์ ตัวอย่างเช่น 0.5, -1 และ 1,000 ทั้งหมดจะล้มเหลวด้วยคำตอบนี้และพวกเขาจะเป็นตัวเลขที่สมบูรณ์แบบ
Simeon G

125

ตามที่ @CraigTP ได้กล่าวถึงในคำตอบที่ยอดเยี่ยมของเขาฉันยังมีความกังวลเกี่ยวกับประสิทธิภาพที่คล้ายกันในการใช้การยกเว้นเพื่อทดสอบว่าสตริงนั้นเป็นตัวเลขหรือไม่ java.lang.Character.isDigit()ดังนั้นผมจึงจบลงด้วยการแยกสตริงและการใช้งาน

public static boolean isNumeric(String str)
{
    for (char c : str.toCharArray())
    {
        if (!Character.isDigit(c)) return false;
    }
    return true;
}

ตามJavadoc , Character.isDigit(char)จะถูกต้องตระหนักถึงตัวเลขที่ไม่ใช่ละติน ฉันคิดว่าการเปรียบเทียบจำนวน N อย่างง่าย ๆ ที่ N คือจำนวนอักขระในสตริงจะมีประสิทธิภาพในการคำนวณมากกว่าการจับคู่ regex

ปรับปรุง: ตามที่ชี้ไปที่ Jean-François Corbett ในความคิดเห็นรหัสข้างต้นจะตรวจสอบจำนวนเต็มบวกเท่านั้นซึ่งครอบคลุมส่วนใหญ่ของกรณีการใช้งานของฉัน ด้านล่างคือรหัสที่อัปเดตซึ่งตรวจสอบความถูกต้องของตัวเลขทศนิยมตามตำแหน่งที่ตั้งเริ่มต้นที่ใช้ในระบบของคุณอย่างถูกต้องโดยมีสมมติฐานว่าตัวแยกเลขทศนิยมเกิดขึ้นเพียงครั้งเดียวในสตริง

public static boolean isStringNumeric( String str )
{
    DecimalFormatSymbols currentLocaleSymbols = DecimalFormatSymbols.getInstance();
    char localeMinusSign = currentLocaleSymbols.getMinusSign();

    if ( !Character.isDigit( str.charAt( 0 ) ) && str.charAt( 0 ) != localeMinusSign ) return false;

    boolean isDecimalSeparatorFound = false;
    char localeDecimalSeparator = currentLocaleSymbols.getDecimalSeparator();

    for ( char c : str.substring( 1 ).toCharArray() )
    {
        if ( !Character.isDigit( c ) )
        {
            if ( c == localeDecimalSeparator && !isDecimalSeparatorFound )
            {
                isDecimalSeparatorFound = true;
                continue;
            }
            return false;
        }
    }
    return true;
}

4
ตัวคั่นทศนิยมจะไม่ทำให้สิ่งนี้ล้มเหลวด้วยหรือไม่
Jean-François Corbett

1
@ Jean-FrançoisCorbett: จุดดีฉันได้อัปเดตรหัสด้วยอันใหม่ที่ยอมรับตัวคั่นทศนิยม
Ibrahim Arief

2
เครื่องหมาย -ve ไม่ทำงานของฟังก์ชันนี้หรือไม่
java_mouse

3
การเรียกtoCharArray()จะสร้างสำเนาของอาร์เรย์ในวัตถุ String เนื่องจาก Strings ไม่เปลี่ยนรูป อาจเร็วกว่านี้ในการใช้charAt(int index)วิธีการกับวัตถุ String โดยตรง
Mike Kucera

2
จะสร้างStringIndexOutOfBoundsExceptionเมื่อผ่านสตริงที่มีความยาว 0 สามารถแก้ไขได้ด้วยif(str.length() == 0) return false;
samgak

43

ห้องสมุดฝรั่งของ Google Ints.tryParseยังมีวิธีการช่วยเหลือที่ดีที่จะทำเช่นนี้: คุณใช้มันชอบInteger.parseIntแต่มันจะส่งกลับnullมากกว่าโยนข้อยกเว้นถ้าสตริงไม่ได้แยกเป็นจำนวนเต็มที่ถูกต้อง โปรดทราบว่ามันคืนค่า Integer ไม่ใช่ int ดังนั้นคุณต้องแปลง / autobox กลับเป็น int

ตัวอย่าง:

String s1 = "22";
String s2 = "22.2";
Integer oInt1 = Ints.tryParse(s1);
Integer oInt2 = Ints.tryParse(s2);

int i1 = -1;
if (oInt1 != null) {
    i1 = oInt1.intValue();
}
int i2 = -1;
if (oInt2 != null) {
    i2 = oInt2.intValue();
}

System.out.println(i1);  // prints 22
System.out.println(i2);  // prints -1

อย่างไรก็ตามในขณะที่รีลีสปัจจุบัน - Guava r11 - ยังคงถูกทำเครื่องหมาย @Beta

ฉันไม่ได้เปรียบเทียบมัน การดูซอร์สโค้ดนั้นมีค่าโสหุ้ยจากการตรวจสุขภาพอย่างมาก แต่ในที่สุดพวกเขาก็ใช้งานที่Character.digit(string.charAt(idx))คล้ายกัน แต่แตกต่างกันเล็กน้อยจากคำตอบจาก @Ibrahim ด้านบน ไม่มีข้อยกเว้นในการจัดการค่าใช้จ่ายภายใต้ฝาครอบในการใช้งาน


ระวังว่าสิ่งนี้จะส่ง NPE ในกรณีที่อาร์กิวเมนต์เป็นโมฆะ
Vadzim

30

อย่าใช้ข้อยกเว้นเพื่อตรวจสอบค่าของคุณ ใช้ libs Util แทนเช่น apache NumberUtils:

NumberUtils.isNumber(myStringValue);

แก้ไข :

โปรดสังเกตว่าหากสตริงของคุณเริ่มต้นด้วย 0 NumberUtils จะตีความค่าของคุณเป็นเลขฐานสิบหก

NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false

7
Number.isNumber()คำตอบที่ได้รับการยอมรับสามปีก่อนหน้านี้ที่กล่าวมาแล้ว
Andy Thomas

ฉันไม่คิดอย่างนั้น มันได้รับการปรับปรุงหรือเปลี่ยนคำตอบที่ยอมรับแล้ว ฉันจำได้ว่าคำตอบที่ได้รับการยอมรับไม่ได้ครอบคลุม NumberUtils นั่นเป็นเหตุผลที่ฉันเพิ่มคำตอบของฉัน แต่ขอบคุณสำหรับความคิดเห็น
Goot

2
@Goot - ประวัติของคำตอบที่ยอมรับแสดงให้เห็นว่าNumber.isNumber()มีอยู่ในรุ่นแรกของคำตอบลงวันที่ 24 กันยายน 12 ที่ 17:01
Andy Thomas

@Goot มันค่อนข้างดีเพราะครอบคลุมการตรวจสอบค่าทศนิยมซึ่งแตกต่างจาก StringUtils
Heena Hussain

24

ทำไมทุกคนผลักดันให้เกิดข้อยกเว้น / โซลูชั่น regex?

ในขณะที่ฉันสามารถเข้าใจคนส่วนใหญ่ได้ดีกับการใช้ลอง / จับถ้าคุณต้องการทำบ่อย ๆ ... มันสามารถเดินทางโดยรถแท็กซี่มาก

สิ่งที่ฉันทำที่นี่คือใช้ regex, parseNumber () วิธีและวิธีการค้นหาอาร์เรย์เพื่อดูว่ามีประสิทธิภาพมากที่สุด ครั้งนี้ฉันดูที่ตัวเลขจำนวนเต็มเท่านั้น

public static boolean isNumericRegex(String str) {
    if (str == null)
        return false;
    return str.matches("-?\\d+");
}

public static boolean isNumericArray(String str) {
    if (str == null)
        return false;
    char[] data = str.toCharArray();
    if (data.length <= 0)
        return false;
    int index = 0;
    if (data[0] == '-' && data.length > 1)
        index = 1;
    for (; index < data.length; index++) {
        if (data[index] < '0' || data[index] > '9') // Character.isDigit() can go here too.
            return false;
    }
    return true;
}

public static boolean isNumericException(String str) {
    if (str == null)
        return false;
    try {  
        /* int i = */ Integer.parseInt(str);
    } catch (NumberFormatException nfe) {  
        return false;  
    }
    return true;
}

ผลลัพธ์ความเร็วที่ฉันได้คือ:

Done with: for (int i = 0; i < 10000000; i++)...

With only valid numbers ("59815833" and "-59815833"):
    Array numeric took 395.808192 ms [39.5808192 ns each]
    Regex took 2609.262595 ms [260.9262595 ns each]
    Exception numeric took 428.050207 ms [42.8050207 ns each]
    // Negative sign
    Array numeric took 355.788273 ms [35.5788273 ns each]
    Regex took 2746.278466 ms [274.6278466 ns each]
    Exception numeric took 518.989902 ms [51.8989902 ns each]
    // Single value ("1")
    Array numeric took 317.861267 ms [31.7861267 ns each]
    Regex took 2505.313201 ms [250.5313201 ns each]
    Exception numeric took 239.956955 ms [23.9956955 ns each]
    // With Character.isDigit()
    Array numeric took 400.734616 ms [40.0734616 ns each]
    Regex took 2663.052417 ms [266.3052417 ns each]
    Exception numeric took 401.235906 ms [40.1235906 ns each]

With invalid characters ("5981a5833" and "a"):
    Array numeric took 343.205793 ms [34.3205793 ns each]
    Regex took 2608.739933 ms [260.8739933 ns each]
    Exception numeric took 7317.201775 ms [731.7201775 ns each]
    // With a single character ("a")
    Array numeric took 291.695519 ms [29.1695519 ns each]
    Regex took 2287.25378 ms [228.725378 ns each]
    Exception numeric took 7095.969481 ms [709.5969481 ns each]

With null:
    Array numeric took 214.663834 ms [21.4663834 ns each]
    Regex took 201.395992 ms [20.1395992 ns each]
    Exception numeric took 233.049327 ms [23.3049327 ns each]
    Exception numeric took 6603.669427 ms [660.3669427 ns each] if there is no if/null check

ข้อจำกัดความรับผิดชอบ: ฉันไม่ได้อ้างว่าวิธีการเหล่านี้ได้รับการปรับให้เหมาะสม 100% แต่เป็นเพียงเพื่อสาธิตข้อมูล

ข้อยกเว้นจะชนะถ้าหากมีเพียง 4 ตัวอักษรหรือน้อยกว่าและทุก ๆ สตริงจะเป็นตัวเลขเสมอ ... ในกรณีใดทำไมถึงต้องมีเช็ค?

กล่าวโดยย่อก็คือเจ็บปวดอย่างมากหากคุณพบตัวเลขที่ไม่ถูกต้องบ่อยครั้งด้วยการลอง / จับซึ่งทำให้เข้าใจได้ กฎที่สำคัญผมมักจะทำตามจะไม่เคยใช้ลอง / จับสำหรับการไหลของโปรแกรม นี่คือตัวอย่างว่าทำไม

ที่น่าสนใจคือง่ายๆถ้าถ่าน <0 || > 9 นั้นง่ายมากที่จะเขียนจำได้ง่าย (และควรทำงานในหลายภาษา) และชนะเกือบทุกสถานการณ์การทดสอบ

ข้อเสียเพียงอย่างเดียวคือฉันเดาว่า Integer.parseInt () อาจจัดการกับตัวเลขที่ไม่ใช่ ASCII ในขณะที่วิธีการค้นหาอาร์เรย์ไม่ได้


สำหรับคนที่สงสัยว่าทำไมฉันถึงบอกว่ามันง่ายที่จะจดจำอาเรย์ตัวละครตัวหนึ่งถ้าคุณรู้ว่ามันไม่มีสัญญาณเชิงลบ

public static boolean isNumericArray(String str) {
    if (str == null)
        return false;
    for (char c : str.toCharArray())
        if (c < '0' || c > '9')
            return false;
    return true;

สุดท้ายเป็นบันทึกสุดท้ายฉันอยากรู้เกี่ยวกับผู้ประกอบการในตัวอย่างที่ได้รับการยอมรับด้วยคะแนนเสียงทั้งหมดขึ้น เพิ่มในการมอบหมายของ

double d = Double.parseDouble(...)

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

คุณอาจคิดว่ามันจะได้รับการปรับปรุงให้ดีที่สุด ... ถึงแม้ว่าฉันควรตรวจสอบรหัสไบต์และดูว่าคอมไพเลอร์กำลังทำอะไรอยู่ นั่นไม่ได้อธิบายว่าทำไมมันจึงปรากฏขึ้นเป็นระยะยาวสำหรับฉันแม้ว่ามันจะได้รับการปรับปรุงให้ดีที่สุด ... ดังนั้นฉันจึงสงสัยว่าเกิดอะไรขึ้น ตามหมายเหตุ: โดยความยาวฉันหมายถึงการรันการทดสอบซ้ำ 10,000,000 ครั้งและการรันโปรแกรมนั้นหลาย ๆ ครั้ง (10x +) แสดงว่ามันช้าลงเสมอ

แก้ไข: อัปเดตการทดสอบสำหรับ Character.isDigit ()


4
สิ่งนี้ไม่ได้รวบรวมการแสดงออกปกติใหม่ทุกครั้งหรือไม่ ดูเหมือนจะไม่มีประสิทธิภาพมากนัก
ซามูเอลเอ็ดวินวอร์ด

1
@SamuelEdwinWard นั่นเป็นเหตุผลทั้งหมดที่ฉันทำโพสต์นี้ ... ตัวอย่าง regex ใช้คำตอบที่ให้โดยคนอื่นและแสดงให้เห็นว่ามันไม่มีประสิทธิภาพแค่ไหน แม้ว่าคุณจะพยายาม regex ด้วยการรวบรวมล่วงหน้าล่วงหน้าและใช้เฉพาะเวลานั้นความแตกต่างของเวลาคือ: 2587 ms สำหรับ regex ที่ฉันโพสต์จากบุคคลอื่นที่ให้ไว้ 950 ms เมื่อรวบรวมล่วงหน้าเวลา 144 ms เมื่อทำมันเป็น อาร์เรย์ที่เป็นตัวเลข (สำหรับการวนซ้ำ 1 ล้านของสตริงเดียวกัน) การรวบรวมล่วงหน้าช่วยให้เห็นได้ชัด แต่น่าเสียดายที่มันยังค่อนข้างด้อยกว่าวิธีการเรียงลำดับ ... เว้นแต่จะมีการเพิ่มประสิทธิภาพบ้า ๆ ที่ฉันไม่รู้
น้ำ

เชื่อว่า Regex ทำให้สิ่งต่าง ๆ เร็วขึ้นเกือบจะเป็นความผิดพลาด ถ้ามันเป็นการค้นหาที่ใช่ฉันได้ ... แต่ฉันได้สังเกตเห็นว่าโค้ดที่เขียนอย่างมีประสิทธิภาพเกินกว่าจะทำให้คุณตกใจ! โพสต์ที่ยอดเยี่ยม @ Water
Yo Apps

19
public static boolean isNumeric(String str)
{
    return str.matches("-?\\d+(.\\d+)?");
}

การแสดงออกปกติของ CraigTP (แสดงด้านบน) ก่อให้เกิดผลบวกปลอมบางอย่าง เช่น "23y4" จะถูกนับเป็นตัวเลขเพราะ '.' จับคู่อักขระใด ๆ ที่ไม่ใช่จุดทศนิยม

นอกจากนี้มันจะปฏิเสธหมายเลขใด ๆ ที่มีเครื่องหมาย '+'

ทางเลือกที่หลีกเลี่ยงปัญหาเล็กน้อยทั้งสองนี้คือ

public static boolean isNumeric(String str)
{
    return str.matches("[+-]?\\d*(\\.\\d+)?");
}

สิ่งนี้จะส่งคืนtrueสำหรับการบวก"+"หรือลบครั้งเดียว"-"และfalseสำหรับ"0."
user85421

จับที่ดีในการบวกเดียวหรือลบ คือ "0" หมายเลขที่ถูกต้อง?
user872985

"0."ถูกต้องDouble.parseDouble()และเป็นตัวอักษรที่ถูกต้องตาม JLS ( §3.10.2 )!
user85421

การสร้างนิพจน์ทั่วไปนั้นมีค่าใช้จ่ายเช่นกัน ต้องสร้างนิพจน์ปกติหนึ่งครั้งและนำมาใช้ใหม่
Daniel Nuriyev

1
คุณควรเปลี่ยนเป็นmatches("-?\\d+([.]\\d+)?")
Bobs

14

เราสามารถลองแทนที่ตัวเลขทั้งหมดจากสตริงที่กำหนดด้วย ("") เช่นช่องว่างและถ้าหลังจากนั้นความยาวของสตริงเป็นศูนย์จากนั้นเราสามารถพูดได้ว่าสตริงที่กำหนดมีตัวเลขเท่านั้น [หากคุณพบว่าคำตอบนี้มีประโยชน์โปรดพิจารณาการลงคะแนน] ตัวอย่าง:

boolean isNumber(String str){
        if(str.length() == 0)
            return false; //To check if string is empty

        if(str.charAt(0) == '-')
            str = str.replaceFirst("-","");// for handling -ve numbers

        System.out.println(str);

        str = str.replaceFirst("\\.",""); //to check if it contains more than one decimal points

        if(str.length() == 0)
            return false; // to check if it is empty string after removing -ve sign and decimal point
        System.out.println(str);

        return str.replaceAll("[0-9]","").length() == 0;
    }

ดังนั้น""จำนวน แต่"3.14"และ"-1"ไม่?
Eric Duminil

เห็นได้ชัดว่าใช้ไม่ได้กับทุกรูปแบบตัวเลข แต่นี่คือ upvote สำหรับความคิดที่แตกต่าง ... ถ้าความคิดเดิมเป็นของคุณนั่นคือ
gbenroscience

12

คุณสามารถใช้NumberFormat#parse:

try
{
     NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
    // Not a number.
}

เสนอการแก้ไข - .getInstance () ขาดหายไป +1 เพราะนี่คือคำตอบที่ฉันได้ไปเมื่อค้นหาคำถามนี้
8bitjunkie

5
ราคาแพงถ้าใช้อย่าง
กว้างขวาง

1
valueนอกจากนี้ยังจะผ่านถ้ามีอักขระขยะในตอนท้ายของ
ไบรอันไวท์

มันจะสร้างปัญหาโซนาร์ถ้าคุณไม่บันทึกข้อยกเว้น
jmhostalet

1
สิ่งนี้ใช้ได้กับรูปแบบตัวเลข 0x0001 ที่ Double.parseDouble ไม่ทำงาน +1
Seabass77


8

นี่คือคำตอบของฉันสำหรับปัญหา

จับทุกวิธีการอำนวยความสะดวกที่คุณสามารถใช้เพื่อแยกสตริงใด ๆ isParsable(Object parser, String str)กับประเภทของการแยกวิเคราะห์ใด ตัวแยกวิเคราะห์สามารถเป็นหรือClass objectสิ่งนี้จะช่วยให้คุณใช้ตัวแยกวิเคราะห์ที่กำหนดเองที่คุณเขียนและควรใช้งานได้ตลอดเวลาเช่น:

isParsable(Integer.class, "11");
isParsable(Double.class, "11.11");
Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");

นี่คือรหัสของฉันพร้อมคำอธิบายวิธีการ

import java.lang.reflect.*;

/**
 * METHOD: isParsable<p><p>
 * 
 * This method will look through the methods of the specified <code>from</code> parameter
 * looking for a public method name starting with "parse" which has only one String
 * parameter.<p>
 * 
 * The <code>parser</code> parameter can be a class or an instantiated object, eg:
 * <code>Integer.class</code> or <code>new Integer(1)</code>. If you use a
 * <code>Class</code> type then only static methods are considered.<p>
 * 
 * When looping through potential methods, it first looks at the <code>Class</code> associated
 * with the <code>parser</code> parameter, then looks through the methods of the parent's class
 * followed by subsequent ancestors, using the first method that matches the criteria specified
 * above.<p>
 * 
 * This method will hide any normal parse exceptions, but throws any exceptions due to
 * programmatic errors, eg: NullPointerExceptions, etc. If you specify a <code>parser</code>
 * parameter which has no matching parse methods, a NoSuchMethodException will be thrown
 * embedded within a RuntimeException.<p><p>
 * 
 * Example:<br>
 * <code>isParsable(Boolean.class, "true");<br>
 * isParsable(Integer.class, "11");<br>
 * isParsable(Double.class, "11.11");<br>
 * Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");<br>
 * isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");<br></code>
 * <p>
 * 
 * @param parser    The Class type or instantiated Object to find a parse method in.
 * @param str   The String you want to parse
 * 
 * @return true if a parse method was found and completed without exception
 * @throws java.lang.NoSuchMethodException If no such method is accessible 
 */
public static boolean isParsable(Object parser, String str) {
    Class theClass = (parser instanceof Class? (Class)parser: parser.getClass());
    boolean staticOnly = (parser == theClass), foundAtLeastOne = false;
    Method[] methods = theClass.getMethods();

    // Loop over methods
    for (int index = 0; index < methods.length; index++) {
        Method method = methods[index];

        // If method starts with parse, is public and has one String parameter.
        // If the parser parameter was a Class, then also ensure the method is static. 
        if(method.getName().startsWith("parse") &&
            (!staticOnly || Modifier.isStatic(method.getModifiers())) &&
            Modifier.isPublic(method.getModifiers()) &&
            method.getGenericParameterTypes().length == 1 &&
            method.getGenericParameterTypes()[0] == String.class)
        {
            try {
                foundAtLeastOne = true;
                method.invoke(parser, str);
                return true; // Successfully parsed without exception
            } catch (Exception exception) {
                // If invoke problem, try a different method
                /*if(!(exception instanceof IllegalArgumentException) &&
                   !(exception instanceof IllegalAccessException) &&
                   !(exception instanceof InvocationTargetException))
                        continue; // Look for other parse methods*/

                // Parse method refuses to parse, look for another different method
                continue; // Look for other parse methods
            }
        }
    }

    // No more accessible parse method could be found.
    if(foundAtLeastOne) return false;
    else throw new RuntimeException(new NoSuchMethodException());
}


/**
 * METHOD: willParse<p><p>
 * 
 * A convienence method which calls the isParseable method, but does not throw any exceptions
 * which could be thrown through programatic errors.<p>
 * 
 * Use of {@link #isParseable(Object, String) isParseable} is recommended for use so programatic
 * errors can be caught in development, unless the value of the <code>parser</code> parameter is
 * unpredictable, or normal programtic exceptions should be ignored.<p>
 * 
 * See {@link #isParseable(Object, String) isParseable} for full description of method
 * usability.<p>
 * 
 * @param parser    The Class type or instantiated Object to find a parse method in.
 * @param str   The String you want to parse
 * 
 * @return true if a parse method was found and completed without exception
 * @see #isParseable(Object, String) for full description of method usability 
 */
public static boolean willParse(Object parser, String str) {
    try {
        return isParsable(parser, str);
    } catch(Throwable exception) {
        return false;
    }
}

5

หากต้องการจับคู่เลขจำนวนเต็มฐานสิบบวกเท่านั้นที่มีเฉพาะตัวเลข ASCII เท่านั้นให้ใช้:

public static boolean isNumeric(String maybeNumeric) {
    return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
}

5

วิธีการที่มีประสิทธิภาพดีหลีกเลี่ยงการลองจับและจัดการกับจำนวนลบและเครื่องหมายทางวิทยาศาสตร์

Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );

public static boolean isNumeric( String value ) 
{
    return value != null && PATTERN.matcher( value ).matches();
}

5

นี่คือคลาสของฉันสำหรับตรวจสอบว่าสตริงเป็นตัวเลขหรือไม่ นอกจากนี้ยังแก้ไขสตริงตัวเลข:

คุณสมบัติ:

  1. ลบศูนย์ที่ไม่จำเป็น ["12.0000000" -> "12"]
  2. ลบศูนย์ที่ไม่จำเป็น ["12.0580000" -> "12.058"]
  3. ลบอักขระที่ไม่ใช่ตัวเลข ["12.00sdfsdf00" -> "12"]
  4. จัดการค่าสตริงเชิงลบ ["-12,020000" -> "-12.02"]
  5. ลบหลายจุด ["-12.0.20.000" -> "-12.02"]
  6. ไม่มีไลบรารีเพิ่มเติมเพียง Java มาตรฐาน

ที่นี่คุณไป ...

public class NumUtils {
    /**
     * Transforms a string to an integer. If no numerical chars returns a String "0".
     *
     * @param str
     * @return retStr
     */
    static String makeToInteger(String str) {
        String s = str;
        double d;
        d = Double.parseDouble(makeToDouble(s));
        int i = (int) (d + 0.5D);
        String retStr = String.valueOf(i);
        System.out.printf(retStr + "   ");
        return retStr;
    }

    /**
     * Transforms a string to an double. If no numerical chars returns a String "0".
     *
     * @param str
     * @return retStr
     */
    static String makeToDouble(String str) {

        Boolean dotWasFound = false;
        String orgStr = str;
        String retStr;
        int firstDotPos = 0;
        Boolean negative = false;

        //check if str is null
        if(str.length()==0){
            str="0";
        }

        //check if first sign is "-"
        if (str.charAt(0) == '-') {
            negative = true;
        }

        //check if str containg any number or else set the string to '0'
        if (!str.matches(".*\\d+.*")) {
            str = "0";
        }

        //Replace ',' with '.'  (for some european users who use the ',' as decimal separator)
        str = str.replaceAll(",", ".");
        str = str.replaceAll("[^\\d.]", "");

        //Removes the any second dots
        for (int i_char = 0; i_char < str.length(); i_char++) {
            if (str.charAt(i_char) == '.') {
                dotWasFound = true;
                firstDotPos = i_char;
                break;
            }
        }
        if (dotWasFound) {
            String befDot = str.substring(0, firstDotPos + 1);
            String aftDot = str.substring(firstDotPos + 1, str.length());
            aftDot = aftDot.replaceAll("\\.", "");
            str = befDot + aftDot;
        }

        //Removes zeros from the begining
        double uglyMethod = Double.parseDouble(str);
        str = String.valueOf(uglyMethod);

        //Removes the .0
        str = str.replaceAll("([0-9])\\.0+([^0-9]|$)", "$1$2");

        retStr = str;

        if (negative) {
            retStr = "-"+retStr;
        }

        return retStr;

    }

    static boolean isNumeric(String str) {
        try {
            double d = Double.parseDouble(str);
        } catch (NumberFormatException nfe) {
            return false;
        }
        return true;
    }

}

5

การจับคู่ Regex

นี่เป็นอีกตัวอย่างหนึ่งที่อัพเกรดการจับคู่ regex "CraigTP" พร้อมการตรวจสอบเพิ่มเติม

public static boolean isNumeric(String str)
{
    return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
  1. -อนุญาตให้ใช้เครื่องหมายลบได้เพียงหนึ่งป้ายเท่านั้นและต้องอยู่ในจุดเริ่มต้น
  2. หลังจากเครื่องหมายลบต้องมีตัวเลข
  3. .อนุญาตให้ใช้ทศนิยมเพียงหนึ่งป้ายเท่านั้น
  4. หลังจากเครื่องหมายทศนิยมจะต้องมีตัวเลข

การทดสอบ Regex

1                  --                   **VALID**
1.                 --                   INVALID
1..                --                   INVALID
1.1                --                   **VALID**
1.1.1              --                   INVALID

-1                 --                   **VALID**
--1                --                   INVALID
-1.                --                   INVALID
-1.1               --                   **VALID**
-1.1.1             --                   INVALID

5

ข้อยกเว้นมีราคาแพง แต่ในกรณีนี้ RegEx ใช้เวลานานกว่ามาก รหัสด้านล่างแสดงการทดสอบอย่างง่ายของสองฟังก์ชั่น - อันหนึ่งใช้ข้อยกเว้นและอีกอันใช้ regex ในเครื่องของฉันรุ่น RegEx ช้ากว่าข้อยกเว้น 10 เท่า

import java.util.Date;


public class IsNumeric {

public static boolean isNumericOne(String s) {
    return s.matches("-?\\d+(\\.\\d+)?");  //match a number with optional '-' and decimal.      
}

public static boolean isNumericTwo(String s) {
    try {
        Double.parseDouble(s);
        return true;
    } catch (Exception e) {
        return false;
    }
}

public static void main(String [] args) {

    String test = "12345.F";

    long before = new Date().getTime();     
    for(int x=0;x<1000000;++x) {
        //isNumericTwo(test);
        isNumericOne(test);
    }
    long after = new Date().getTime();

    System.out.println(after-before);

}

}

โดยทั่วไปฉันคิดว่ารหัสประเภทนี้จะใช้เพื่อตรวจสอบสิ่งต่างๆเช่นการป้อนข้อมูลที่พิมพ์ ในกรณีที่ความเร็วนั้นไม่ใช่การพิจารณาและทำสิ่งที่น่าเกลียดเหมือนกับการโยนข้อยกเว้นเพื่อตรวจสอบหมายเลขหรือหมายเลขที่ไม่ถูกต้อง
user872985

อาจจะไม่. อินพุตที่พิมพ์มักจะถูกตรวจสอบโดยองค์ประกอบ UI ที่ข้อผิดพลาดสามารถแสดงได้ทันทีก่อนที่จะส่งค่า อาจเป็นเรื่องปกติที่จะตรวจสอบความถูกต้องของสตริงจากไฟล์ข้อความขนาดใหญ่ - ซึ่งเป็นเรื่องของประสิทธิภาพ เป้าหมายในคำตอบของฉันที่นี่คือการระบุคำสั่ง "ข้อยกเว้นช้า" ในคำตอบที่ยอมรับได้ คอมเพล็กซ์ regex มีราคาแพงกว่ามาก และไม่มี "ขี้เหร่ขว้าง" ในรหัสของฉันเลย - เป็นวิธีที่เร็วกว่าในการตรวจจับการละเมิด ด้วยวิธีการตรวจสอบก่อนแล้วคำนวณคุณทำสองผ่านผ่านการป้อนข้อมูล: หนึ่งในการตรวจสอบและจากนั้นอีกหนึ่งการแปลง
ChrisCantrell

5

// โปรดตรวจสอบรหัสด้านล่าง

public static boolean isDigitsOnly(CharSequence str) {
    final int len = str.length();
    for (int i = 0; i < len; i++) {
        if (!Character.isDigit(str.charAt(i))) {
            return false;
        }
    }
    return true;
}

คำถามที่ว่า "ตัวเลข" ซึ่งอาจรวมถึงค่าที่ไม่ใช่จำนวนเต็ม
rghome

3
// only int
public static boolean isNumber(int num) 
{
    return (num >= 48 && c <= 57); // 0 - 9
}

// is type of number including . - e E 
public static boolean isNumber(String s) 
{
    boolean isNumber = true;
    for(int i = 0; i < s.length() && isNumber; i++) 
    {
        char c = s.charAt(i);
        isNumber = isNumber & (
            (c >= '0' && c <= '9') || (c == '.') || (c == 'e') || (c == 'E') || (c == '')
        );
    }
    return isInteger;
}

// is type of number 
public static boolean isInteger(String s) 
{
    boolean isInteger = true;
    for(int i = 0; i < s.length() && isInteger; i++) 
    {
        char c = s.charAt(i);
        isInteger = isInteger & ((c >= '0' && c <= '9'));
    }
    return isInteger;
}

public static boolean isNumeric(String s) 
{
    try
    {
        Double.parseDouble(s);
        return true;
    }
    catch (Exception e) 
    {
        return false;
    }
}

3

นี่เป็นตัวอย่างง่าย ๆ สำหรับการตรวจสอบนี้:

public static boolean isNumericString(String input) {
    boolean result = false;

    if(input != null && input.length() > 0) {
        char[] charArray = input.toCharArray();

        for(char c : charArray) {
            if(c >= '0' && c <= '9') {
                // it is a digit
                result = true;
            } else {
                result = false;
                break;
            }
        }
    }

    return result;
}


2

ฉันปรับเปลี่ยนโซลูชันของ CraigTP เพื่อยอมรับเครื่องหมายทางวิทยาศาสตร์และทั้งจุดและเครื่องหมายจุลภาคเป็นตัวคั่นทศนิยมเช่นกัน

^-?\d+([,\.]\d+)?([eE]-?\d+)?$

ตัวอย่าง

var re = new RegExp("^-?\d+([,\.]\d+)?([eE]-?\d+)?$");
re.test("-6546"); // true
re.test("-6546355e-4456"); // true
re.test("-6546.355e-4456"); // true, though debatable
re.test("-6546.35.5e-4456"); // false
re.test("-6546.35.5e-4456.6"); // false

2

นั่นเป็นเหตุผลที่ฉันชอบวิธีลอง * ใน. NET นอกเหนือจากวิธีการแยกวิเคราะห์แบบดั้งเดิมที่เหมือนกับ Java แล้วคุณยังมีวิธี TryParse ฉันไม่ดีในไวยากรณ์ของ Java (ออกพารามิเตอร์หรือไม่) ดังนั้นโปรดปฏิบัติต่อไปนี้เป็นรหัสหลอกบางชนิด ควรทำให้แนวคิดชัดเจนขึ้น

boolean parseInteger(String s, out int number)
{
    try {
        number = Integer.parseInt(myString);
        return true;
    } catch(NumberFormatException e) {
        return false;
    }
}

การใช้งาน:

int num;
if (parseInteger("23", out num)) {
    // Do something with num.
}

ใช่ไม่มี "out พารามิเตอร์" ใน Java และเนื่องจาก Integer wrapper ไม่เปลี่ยนรูป (จึงไม่สามารถใช้เป็นข้อมูลอ้างอิงที่ถูกต้องในการจัดเก็บผลลัพธ์) ตัวเลือกที่เข้าใจง่ายจะส่งคืนวัตถุ Integer ที่อาจเป็นโมฆะถ้าการแยกวิเคราะห์ ล้มเหลว ตัวเลือก uglier อาจจะผ่าน int [1] เป็นพารามิเตอร์เอาต์พุต
fortran

ใช่ฉันจำการอภิปรายเกี่ยวกับสาเหตุที่ Java ไม่มีพารามิเตอร์เอาต์พุต แต่การคืนค่าจำนวนเต็ม (เป็นโมฆะถ้าจำเป็น) ก็คงใช้ได้เช่นกันฉันเดาว่าถึงแม้ว่าฉันไม่รู้เกี่ยวกับประสิทธิภาพของ Java เกี่ยวกับการชกมวย / การเลิกทำกล่อง
OregonGhost

4
ฉันชอบ C # มากเท่ากับผู้ชายคนต่อไป แต่ไม่มีประโยชน์ที่จะเพิ่มข้อมูลโค้ด. NET C # สำหรับคำถาม Java เมื่อไม่มีคุณสมบัติใน Java
Shane

มันจะสร้างปัญหาโซนาร์ถ้าคุณไม่บันทึกข้อยกเว้น
jmhostalet

2

แยกมัน (เช่นกับInteger#parseInt) และก็จับข้อยกเว้น =)

เพื่อชี้แจง: ฟังก์ชั่น parseInt ตรวจสอบว่ามันสามารถแยกตัวเลขในกรณีใด ๆ (ชัด) และถ้าคุณต้องการที่จะแยกมันต่อไปคุณจะไม่ใช้ประสิทธิภาพการตีโดยการแยกวิเคราะห์จริง ๆ

หากคุณไม่ต้องการแยกวิเคราะห์มัน (หรือแยกวิเคราะห์มันน้อยมาก) คุณอาจต้องการทำมันแตกต่างกันแน่นอน


1
ค่าใช้จ่ายสูงหากใช้อย่าง
กว้างขวาง

มันจะสร้างปัญหาโซนาร์ถ้าคุณไม่บันทึกข้อยกเว้น
jmhostalet

Double.parseDouble
Alex78191

2

คุณสามารถใช้ NumberUtils.isCreatable () จากApache คอมมอนส์แลง

เนื่องจาก NumberUtils.isNumber จะถูกคัดค้านใน 4.0 ดังนั้นให้ใช้ NumberUtils.isCreatable () แทน


2

Java 8 Stream, การแสดงออกแลมบ์ดา, ส่วนต่อประสานการทำงาน

จัดการทุกกรณี ( สตริงว่าง, สตริงว่าง ฯลฯ )

String someString = null; // something="", something="123abc", something="123123"

boolean isNumeric = Stream.of(someString)
            .filter(s -> s != null && !s.isEmpty())
            .filter(Pattern.compile("\\D").asPredicate().negate())
            .mapToLong(Long::valueOf)
            .boxed()
            .findAny()
            .isPresent();

2

ฉันได้แสดงเงื่อนไขบางประการเพื่อตรวจสอบหมายเลขและทศนิยมโดยไม่ใช้ API ใด ๆ

ตรวจสอบความยาวตัวแก้ไข 1 หลัก

Character.isDigit(char)

ตรวจสอบหมายเลข Fix Length (สมมติว่าความยาวเท่ากับ 6)

String number = "132452";
if(number.matches("([0-9]{6})"))
System.out.println("6 digits number identified");

ตรวจสอบหมายเลขความยาวแปรผันระหว่าง (สมมติความยาว 4 ถึง 6)

//  {n,m}  n <= length <= m
String number = "132452";
if(number.matches("([0-9]{4,6})"))
System.out.println("Number Identified between 4 to 6 length");

String number = "132";
if(!number.matches("([0-9]{4,6})"))
System.out.println("Number not in length range or different format");

ตรวจสอบหมายเลขทศนิยมความยาวแปรผันระหว่าง (สมมติความยาว 4 ถึง 7)

//  It will not count the '.' (Period) in length
String decimal = "132.45";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");

String decimal = "1.12";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");

String decimal = "1234";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");

String decimal = "-10.123";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");

String decimal = "123..4";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");

String decimal = "132";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");

String decimal = "1.1";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");

หวังว่ามันจะช่วยคนมากมาย


2

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

มันตรวจสอบได้สูงสุดหนึ่งเครื่องหมายลบและตรวจสอบได้สูงสุดหนึ่งจุดทศนิยม

นี่คือตัวอย่างและผลลัพธ์:

ส่งคืน "1", "-1", "-1.5" และ "-1.556"

"1..5", "1A.5", "1.5D", "-" และ "--1" คืนค่าเท็จ

หมายเหตุ: หากจำเป็นคุณสามารถแก้ไขสิ่งนี้เพื่อยอมรับพารามิเตอร์ Locale และส่งผ่านไปยังการเรียก DecimalFormatSymbols.getInstance () เพื่อใช้ Locale เฉพาะแทนที่จะเป็นพารามิเตอร์ปัจจุบัน

 public static boolean isNumeric(final String input) {
    //Check for null or blank string
    if(input == null || input.isBlank()) return false;

    //Retrieve the minus sign and decimal separator characters from the current Locale
    final var localeMinusSign = DecimalFormatSymbols.getInstance().getMinusSign();
    final var localeDecimalSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator();

    //Check if first character is a minus sign
    final var isNegative = input.charAt(0) == localeMinusSign;
    //Check if string is not just a minus sign
    if (isNegative && input.length() == 1) return false;

    var isDecimalSeparatorFound = false;

    //If the string has a minus sign ignore the first character
    final var startCharIndex = isNegative ? 1 : 0;

    //Check if each character is a number or a decimal separator
    //and make sure string only has a maximum of one decimal separator
    for (var i = startCharIndex; i < input.length(); i++) {
        if(!Character.isDigit(input.charAt(i))) {
            if(input.charAt(i) == localeDecimalSeparator && !isDecimalSeparatorFound) {
                isDecimalSeparatorFound = true;
            } else return false;
        }
    }
    return true;
}

1

นี่คือวิธีการสองวิธีที่อาจใช้งานได้ (โดยไม่ใช้ข้อยกเว้น) หมายเหตุ: Java เป็นค่า pass-by-value โดยค่าเริ่มต้นและค่าของ String คือที่อยู่ของข้อมูลวัตถุของ String ดังนั้นเมื่อคุณทำ

stringNumber = stringNumber.replaceAll(" ", "");

คุณได้เปลี่ยนค่าอินพุตให้ไม่มีช่องว่าง คุณสามารถลบบรรทัดนั้นได้ถ้าต้องการ

private boolean isValidStringNumber(String stringNumber)
{
    if(stringNumber.isEmpty())
    {
        return false;
    }

    stringNumber = stringNumber.replaceAll(" ", "");

    char [] charNumber = stringNumber.toCharArray();
    for(int i =0 ; i<charNumber.length ;i++)
    {
        if(!Character.isDigit(charNumber[i]))
        {
            return false;
        }
    }
    return true;
}

นี่คือวิธีอื่นในกรณีที่คุณต้องการอนุญาตให้ลอยวิธีนี้ถูกกล่าวหาว่าอนุญาตให้ตัวเลขในรูปแบบผ่าน 1,123,123,123,123,123.123 ฉันเพิ่งทำไปและฉันคิดว่ามันต้องมีการทดสอบเพิ่มเติมเพื่อให้แน่ใจว่ามันทำงานได้

private boolean isValidStringTrueNumber(String stringNumber)
{
    if(stringNumber.isEmpty())
    {
        return false;
    }

    stringNumber = stringNumber.replaceAll(" ", "");
    int countOfDecimalPoint = 0;
    boolean decimalPointPassed = false;
    boolean commaFound = false;
    int countOfDigitsBeforeDecimalPoint = 0;
    int countOfDigitsAfterDecimalPoint =0 ;
    int commaCounter=0;
    int countOfDigitsBeforeFirstComma = 0;

    char [] charNumber = stringNumber.toCharArray();
    for(int i =0 ; i<charNumber.length ;i++)
    {
        if((commaCounter>3)||(commaCounter<0))
        {
            return false;
        }
        if(!Character.isDigit(charNumber[i]))//Char is not a digit.
        {
            if(charNumber[i]==',')
            {
                if(decimalPointPassed)
                {
                    return false;
                }
                commaFound = true;
                //check that next three chars are only digits.
                commaCounter +=3;
            }
            else if(charNumber[i]=='.')
            {
                decimalPointPassed = true;
                countOfDecimalPoint++;
            }
            else
            {
                return false;
            }
        }
        else //Char is a digit.
        {
            if ((commaCounter>=0)&&(commaFound))
            {
                if(!decimalPointPassed)
                {
                    commaCounter--;
                }
            }

            if(!commaFound)
            {
                countOfDigitsBeforeFirstComma++;
            }

            if(!decimalPointPassed)
            {
                countOfDigitsBeforeDecimalPoint++;
            }
            else
            {
                countOfDigitsAfterDecimalPoint++;
            }
        }
    }
    if((commaFound)&&(countOfDigitsBeforeFirstComma>3))
    {
        return false;
    }
    if(countOfDecimalPoint>1)
    {
        return false;
    }

    if((decimalPointPassed)&&((countOfDigitsBeforeDecimalPoint==0)||(countOfDigitsAfterDecimalPoint==0)))
    {
        return false;
    }
    return true;
}

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