คุณจะตรวจสอบว่า String เป็นตัวเลขก่อนที่จะแยกวิเคราะห์ได้อย่างไร
Integer.parseInt()
NumberFormatException
คุณจะตรวจสอบว่า String เป็นตัวเลขก่อนที่จะแยกวิเคราะห์ได้อย่างไร
Integer.parseInt()
NumberFormatException
คำตอบ:
ด้วยApache คอมมอนส์แลง 3.5 ขึ้นไป: หรือNumberUtils.isCreatable
StringUtils.isNumeric
ด้วยApache คอมมอนส์แลง 3.4 และด้านล่าง: หรือNumberUtils.isNumber
StringUtils.isNumeric
นอกจากนี้คุณยังสามารถใช้StringUtils.isNumericSpace
ที่ส่งกลับtrue
สำหรับสตริงว่างและละเว้นช่องว่างภายในในสตริง อีกวิธีหนึ่งคือการใช้NumberUtils.isParsable
ซึ่งโดยทั่วไปตรวจสอบหมายเลขจะแยกวิเคราะห์ตาม Java (javadocs ที่เชื่อมโยงมีตัวอย่างโดยละเอียดสำหรับแต่ละวิธี)
StringUtils.isNumeric()
อาจจะไม่เหมาะสมที่นี่เพราะมันจะตรวจสอบเพียงว่าสตริงเป็นลำดับของตัวเลข จะดีสำหรับ ints มากที่สุด แต่ไม่ได้สำหรับตัวเลขที่มีทศนิยมแยกกลุ่ม ฯลฯ
StringUtils
ไม่สนับสนุนสัญญาณนำ แต่คุณควรตรวจสอบNumberUtils.isCreatable
มันรองรับเนกาทีฟอย่างถูกต้อง
โดยทั่วไปจะทำด้วยฟังก์ชั่นที่ผู้ใช้กำหนดเอง (เช่นฟังก์ชั่น 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();
}
.
ใน regex ของคุณจะตรงกับตัวละครใด ๆ ไม่เพียง แต่ตัวแยกทศนิยม
หากคุณใช้ Android คุณควรใช้:
android.text.TextUtils.isDigitsOnly(CharSequence str)
ให้มันง่าย ส่วนใหญ่ทุกคนสามารถ "re-program" (สิ่งเดียวกัน)
.
,-
นิพจน์แลมบ์ดา Java 8
String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );
ตามที่ @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;
}
toCharArray()
จะสร้างสำเนาของอาร์เรย์ในวัตถุ String เนื่องจาก Strings ไม่เปลี่ยนรูป อาจเร็วกว่านี้ในการใช้charAt(int index)
วิธีการกับวัตถุ String โดยตรง
StringIndexOutOfBoundsException
เมื่อผ่านสตริงที่มีความยาว 0 สามารถแก้ไขได้ด้วยif(str.length() == 0) return false;
ห้องสมุดฝรั่งของ 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 ด้านบน ไม่มีข้อยกเว้นในการจัดการค่าใช้จ่ายภายใต้ฝาครอบในการใช้งาน
อย่าใช้ข้อยกเว้นเพื่อตรวจสอบค่าของคุณ ใช้ libs Util แทนเช่น apache NumberUtils:
NumberUtils.isNumber(myStringValue);
แก้ไข :
โปรดสังเกตว่าหากสตริงของคุณเริ่มต้นด้วย 0 NumberUtils จะตีความค่าของคุณเป็นเลขฐานสิบหก
NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false
Number.isNumber()
คำตอบที่ได้รับการยอมรับสามปีก่อนหน้านี้ที่กล่าวมาแล้ว
Number.isNumber()
มีอยู่ในรุ่นแรกของคำตอบลงวันที่ 24 กันยายน 12 ที่ 17:01
ทำไมทุกคนผลักดันให้เกิดข้อยกเว้น / โซลูชั่น 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 ()
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."
matches("-?\\d+([.]\\d+)?")
เราสามารถลองแทนที่ตัวเลขทั้งหมดจากสตริงที่กำหนดด้วย ("") เช่นช่องว่างและถ้าหลังจากนั้นความยาวของสตริงเป็นศูนย์จากนั้นเราสามารถพูดได้ว่าสตริงที่กำหนดมีตัวเลขเท่านั้น [หากคุณพบว่าคำตอบนี้มีประโยชน์โปรดพิจารณาการลงคะแนน] ตัวอย่าง:
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"
ไม่?
คุณสามารถใช้NumberFormat#parse
:
try
{
NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
// Not a number.
}
value
นอกจากนี้ยังจะผ่านถ้ามีอักขระขยะในตอนท้ายของ
หากคุณใช้จาวาเพื่อพัฒนาแอป Android คุณสามารถใช้ฟังก์ชันTextUtils.isDigitsOnly
นี่คือคำตอบของฉันสำหรับปัญหา
จับทุกวิธีการอำนวยความสะดวกที่คุณสามารถใช้เพื่อแยกสตริงใด ๆ 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;
}
}
หากต้องการจับคู่เลขจำนวนเต็มฐานสิบบวกเท่านั้นที่มีเฉพาะตัวเลข ASCII เท่านั้นให้ใช้:
public static boolean isNumeric(String maybeNumeric) {
return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
}
วิธีการที่มีประสิทธิภาพดีหลีกเลี่ยงการลองจับและจัดการกับจำนวนลบและเครื่องหมายทางวิทยาศาสตร์
Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );
public static boolean isNumeric( String value )
{
return value != null && PATTERN.matcher( value ).matches();
}
นี่คือคลาสของฉันสำหรับตรวจสอบว่าสตริงเป็นตัวเลขหรือไม่ นอกจากนี้ยังแก้ไขสตริงตัวเลข:
ที่นี่คุณไป ...
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;
}
}
การจับคู่ Regex
นี่เป็นอีกตัวอย่างหนึ่งที่อัพเกรดการจับคู่ regex "CraigTP" พร้อมการตรวจสอบเพิ่มเติม
public static boolean isNumeric(String str)
{
return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
การทดสอบ 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
ข้อยกเว้นมีราคาแพง แต่ในกรณีนี้ 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);
}
}
// โปรดตรวจสอบรหัสด้านล่าง
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;
}
// 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;
}
}
นี่เป็นตัวอย่างง่าย ๆ สำหรับการตรวจสอบนี้:
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;
}
คุณสามารถใช้วัตถุ java.util.Scanner
public static boolean isNumeric(String inputData) {
Scanner sc = new Scanner(inputData);
return sc.hasNextInt();
}
ฉันปรับเปลี่ยนโซลูชันของ 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
นั่นเป็นเหตุผลที่ฉันชอบวิธีลอง * ใน. 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.
}
แยกมัน (เช่นกับInteger#parseInt
) และก็จับข้อยกเว้น =)
เพื่อชี้แจง: ฟังก์ชั่น parseInt ตรวจสอบว่ามันสามารถแยกตัวเลขในกรณีใด ๆ (ชัด) และถ้าคุณต้องการที่จะแยกมันต่อไปคุณจะไม่ใช้ประสิทธิภาพการตีโดยการแยกวิเคราะห์จริง ๆ
หากคุณไม่ต้องการแยกวิเคราะห์มัน (หรือแยกวิเคราะห์มันน้อยมาก) คุณอาจต้องการทำมันแตกต่างกันแน่นอน
คุณสามารถใช้ NumberUtils.isCreatable () จากApache คอมมอนส์แลง
เนื่องจาก NumberUtils.isNumber จะถูกคัดค้านใน 4.0 ดังนั้นให้ใช้ NumberUtils.isCreatable () แทน
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();
ฉันได้แสดงเงื่อนไขบางประการเพื่อตรวจสอบหมายเลขและทศนิยมโดยไม่ใช้ 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");
หวังว่ามันจะช่วยคนมากมาย
ตามคำตอบอื่น ๆ ฉันเขียนเองและมันไม่ได้ใช้รูปแบบหรือการแยกวิเคราะห์โดยมีการตรวจสอบข้อยกเว้น
มันตรวจสอบได้สูงสุดหนึ่งเครื่องหมายลบและตรวจสอบได้สูงสุดหนึ่งจุดทศนิยม
นี่คือตัวอย่างและผลลัพธ์:
ส่งคืน "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;
}
นี่คือวิธีการสองวิธีที่อาจใช้งานได้ (โดยไม่ใช้ข้อยกเว้น) หมายเหตุ: 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;
}