Bagaimana Anda memeriksa apakah suatu String adalah angka sebelum menguraikannya?
Integer.parseInt()
akan gagal menguraikan nomor ponsel NumberFormatException
.
Bagaimana Anda memeriksa apakah suatu String adalah angka sebelum menguraikannya?
Integer.parseInt()
akan gagal menguraikan nomor ponsel NumberFormatException
.
Jawaban:
Dengan Apache Commons Lang 3.5 dan lebih tinggi: NumberUtils.isCreatable
atau StringUtils.isNumeric
.
Dengan Apache Commons Lang 3.4 dan di bawah ini: NumberUtils.isNumber
atau StringUtils.isNumeric
.
Anda juga dapat menggunakan StringUtils.isNumericSpace
yang mengembalikan true
string kosong dan mengabaikan spasi internal dalam string. Cara lain adalah dengan menggunakan NumberUtils.isParsable
yang pada dasarnya memeriksa nomor yang dapat diuraikan menurut Java. (The javadocs yang ditautkan berisi contoh terperinci untuk setiap metode.)
StringUtils.isNumeric()
mungkin tidak akan sesuai di sini karena hanya memeriksa apakah string adalah urutan digit. Akan baik untuk sebagian besar int tetapi tidak demikian untuk angka dengan desimal, pemisah grup, dll.
StringUtils
tidak mendukung tanda-tanda terkemuka tetapi Anda harus memeriksa NumberUtils.isCreatable
, ini mendukung negatif dengan benar.
Ini umumnya dilakukan dengan fungsi sederhana yang ditentukan pengguna (yaitu fungsi Roll-your-own "isNumeric").
Sesuatu seperti:
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e){
return false;
}
}
Namun, jika Anda sering memanggil fungsi ini, dan Anda berharap banyak cek gagal karena tidak menjadi angka maka kinerja mekanisme ini tidak akan bagus, karena Anda mengandalkan pengecualian yang dilemparkan untuk setiap kegagalan, yang merupakan operasi yang cukup mahal.
Pendekatan alternatif mungkin menggunakan ekspresi reguler untuk memeriksa validitas menjadi nomor:
public static boolean isNumeric(String str) {
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
Berhati-hatilah dengan mekanisme RegEx di atas, karena akan gagal jika Anda menggunakan angka non-Arab (yaitu angka selain 0 hingga 9). Ini karena bagian "\ d" dari RegEx hanya akan cocok dengan [0-9] dan secara efektif tidak sadar secara numerik secara internasional. (Terima kasih kepada OregonGhost untuk menunjukkan ini!)
Atau bahkan alternatif lain adalah dengan menggunakan Java.text.NumberFormat objek bawaan Java untuk melihat apakah, setelah mengurai string posisi parser berada di akhir string. Jika ya, kita dapat menganggap seluruh string adalah numerik:
public static boolean isNumeric(String str) {
NumberFormat formatter = NumberFormat.getInstance();
ParsePosition pos = new ParsePosition(0);
formatter.parse(str, pos);
return str.length() == pos.getIndex();
}
.
dalam regex Anda akan cocok dengan karakter apa pun, bukan hanya karakter pemisah desimal.
Jika Anda menggunakan Android, maka Anda harus menggunakan:
android.text.TextUtils.isDigitsOnly(CharSequence str)
dokumentasi dapat ditemukan di sini
tetap sederhana . kebanyakan orang dapat "memprogram ulang" (hal yang sama).
.
,-
Ekspresi lambda Java 8
String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );
Seperti @CraigTP telah menyebutkan dalam jawaban yang sangat baik, saya juga memiliki masalah kinerja yang serupa dalam menggunakan Pengecualian untuk menguji apakah string tersebut numerik atau tidak. Jadi saya akhirnya memisahkan string dan menggunakan java.lang.Character.isDigit()
.
public static boolean isNumeric(String str)
{
for (char c : str.toCharArray())
{
if (!Character.isDigit(c)) return false;
}
return true;
}
Menurut Javadoc , Character.isDigit(char)
akan dengan benar mengenali angka non-Latin. Dari segi kinerja, saya pikir perbandingan N sederhana di mana N adalah jumlah karakter dalam string akan lebih efisien secara komputasi daripada melakukan pencocokan regex.
UPDATE: Seperti yang ditunjukkan oleh Jean-François Corbett dalam komentar, kode di atas hanya akan memvalidasi bilangan bulat positif, yang mencakup sebagian besar kasus penggunaan saya. Di bawah ini adalah kode yang diperbarui yang memvalidasi angka desimal dengan benar sesuai dengan lokal default yang digunakan dalam sistem Anda, dengan asumsi bahwa pemisah desimal hanya terjadi satu kali dalam string.
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()
akan membuat salinan array di objek String karena String tidak berubah. Mungkin lebih cepat menggunakan charAt(int index)
metode pada objek String secara langsung.
StringIndexOutOfBoundsException
ketika melewati string dengan panjang 0. Dapat diperbaiki denganif(str.length() == 0) return false;
Perpustakaan Guava Google menyediakan metode pembantu yang baik untuk melakukan hal ini: Ints.tryParse
. Anda menggunakannya seperti Integer.parseInt
tetapi mengembalikan null
daripada melemparkan Pengecualian jika string tidak mem-parsing ke integer yang valid. Perhatikan bahwa ia mengembalikan Integer, bukan int, jadi Anda harus mengonversi / autobox kembali ke int.
Contoh:
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
Namun, pada rilis saat ini - Jambu r11 - masih ditandai @Beta.
Saya belum membandingkannya. Melihat kode sumber ada beberapa overhead dari banyak pemeriksaan kewarasan tetapi pada akhirnya mereka menggunakan Character.digit(string.charAt(idx))
, mirip, tetapi sedikit berbeda dari, jawaban dari @Ibrahim di atas. Tidak ada pengecualian menangani overhead di bawah penutup dalam implementasinya.
Jangan gunakan Pengecualian untuk memvalidasi nilai Anda. Gunakan Util libs sebagai gantinya seperti apache NumberUtils:
NumberUtils.isNumber(myStringValue);
Edit :
Harap perhatikan bahwa, jika string Anda dimulai dengan 0, NumberUtils akan menafsirkan nilai Anda sebagai heksadesimal.
NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false
Number.isNumber()
.
Number.isNumber()
hadir dari versi pertama jawaban, tertanggal 24 Sep 12 pada 17:01.
Mengapa semua orang mendorong solusi pengecualian / regex?
Walaupun saya bisa mengerti kebanyakan orang baik-baik saja dengan menggunakan try / catch, jika Anda ingin sering melakukannya ... itu bisa sangat melelahkan.
Apa yang saya lakukan di sini adalah mengambil regex, metode parseNumber (), dan metode pencarian array untuk melihat mana yang paling efisien. Kali ini, saya hanya melihat angka integer.
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;
}
Hasil dalam kecepatan yang saya dapatkan adalah:
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
Penafian: Saya tidak mengklaim metode ini 100% dioptimalkan, mereka hanya untuk demonstrasi data
Pengecualian dimenangkan jika dan hanya jika jumlahnya 4 karakter atau kurang, dan setiap string selalu angka ... dalam hal ini, mengapa bahkan memiliki cek?
Singkatnya, sangat menyakitkan jika Anda sering menemukan nomor yang tidak valid dengan try / catch, yang masuk akal. Aturan penting yang selalu saya ikuti adalah JANGAN PERNAH menggunakan try / catch untuk aliran program . Ini adalah contoh mengapa.
Menariknya, simpel jika char <0 || > 9 sangat sederhana untuk ditulis, mudah diingat (dan harus bekerja dalam berbagai bahasa) dan memenangkan hampir semua skenario pengujian.
Satu-satunya downside adalah bahwa saya menebak Integer.parseInt () mungkin menangani angka non ASCII, sedangkan metode pencarian array tidak.
Bagi mereka yang bertanya-tanya mengapa saya mengatakan mudah untuk mengingat satu array karakter, jika Anda tahu tidak ada tanda-tanda negatif, Anda dapat dengan mudah lolos dengan sesuatu yang kental seperti ini:
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;
Terakhir sebagai catatan terakhir, saya ingin tahu tentang operator asistensi dalam contoh yang diterima dengan semua suara di atas. Menambahkan penugasan
double d = Double.parseDouble(...)
tidak hanya tidak berguna karena Anda bahkan tidak menggunakan nilai, tetapi juga membuang-buang waktu pemrosesan dan meningkatkan runtime oleh beberapa nanodetik (yang menyebabkan peningkatan 100-200 ms dalam tes). Saya tidak dapat melihat mengapa ada orang yang melakukan itu karena ini adalah pekerjaan tambahan untuk mengurangi kinerja.
Anda akan berpikir bahwa itu akan dioptimalkan ... meskipun mungkin saya harus memeriksa bytecode dan melihat apa yang dilakukan oleh kompiler. Itu tidak menjelaskan mengapa itu selalu tampak lebih panjang bagi saya meskipun jika entah bagaimana dioptimalkan keluar ... karena itu saya bertanya-tanya apa yang terjadi. Sebagai catatan: Secara lebih panjang, maksud saya menjalankan tes untuk 10.000.000 iterasi, dan menjalankan program itu beberapa kali (10x +) selalu menunjukkan itu lebih lambat.
EDIT: Diperbarui tes untuk Character.isDigit ()
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(.\\d+)?");
}
Ekspresi reguler CraigTP (ditampilkan di atas) menghasilkan beberapa positif palsu. Misalnya "23y4" akan dihitung sebagai angka karena '.' cocok dengan karakter apa pun bukan titik desimal.
Juga akan menolak nomor apa pun dengan '+' yang memimpin
Alternatif yang menghindari dua masalah kecil ini adalah
public static boolean isNumeric(String str)
{
return str.matches("[+-]?\\d*(\\.\\d+)?");
}
true
untuk plus "+"
atau minus tunggal "-"
, dan false
untuk"0."
matches("-?\\d+([.]\\d+)?")
Kita dapat mencoba mengganti semua angka dari string yang diberikan dengan ("") yaitu ruang kosong dan jika setelah itu panjang string adalah nol maka kita dapat mengatakan bahwa string yang diberikan hanya berisi angka. [Jika Anda menemukan jawaban ini bermanfaat maka silakan pertimbangkan untuk memilihnya] Contoh:
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;
}
""
adalah angka tetapi "3.14"
dan "-1"
tidak?
Anda bisa menggunakan NumberFormat#parse
:
try
{
NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
// Not a number.
}
value
.
Jika Anda menggunakan java untuk mengembangkan aplikasi Android, Anda bisa menggunakan fungsi TextUtils.isDigitsOnly .
Inilah jawaban saya untuk masalah tersebut.
Sebuah menangkap semua metode kenyamanan yang dapat Anda gunakan untuk mengurai setiap String dengan semua jenis parser: isParsable(Object parser, String str)
. Parser dapat berupa a Class
atau a object
. Ini juga akan memungkinkan Anda untuk menggunakan parser khusus yang Anda tulis dan harus berfungsi untuk skenario sebelumnya, misalnya:
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");
Ini kode saya lengkap dengan deskripsi metode.
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;
}
}
Untuk mencocokkan hanya bilangan bulat basis-sepuluh positif, yang hanya berisi digit ASCII, gunakan:
public static boolean isNumeric(String maybeNumeric) {
return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
}
Pendekatan yang berperforma baik menghindari try-catch dan menangani angka negatif dan notasi ilmiah.
Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );
public static boolean isNumeric( String value )
{
return value != null && PATTERN.matcher( value ).matches();
}
Ini kelas saya untuk memeriksa apakah sebuah string adalah angka. Itu juga memperbaiki string numerik:
Ini dia ...
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;
}
}
Pencocokan Regex
Berikut adalah contoh lain pemutakhiran regex "CraigTP" yang ditingkatkan dengan lebih banyak validasi.
public static boolean isNumeric(String str)
{
return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
Tes 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
Pengecualian itu mahal, tetapi dalam hal ini RegEx membutuhkan waktu lebih lama. Kode di bawah ini menunjukkan tes sederhana dari dua fungsi - satu menggunakan pengecualian dan satu menggunakan regex. Di komputer saya, versi RegEx 10 kali lebih lambat dari pengecualian.
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);
}
}
// silakan periksa kode di bawah ini
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;
}
}
Ini contoh sederhana untuk pemeriksaan ini:
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;
}
Anda dapat menggunakan objek java.util.Scanner.
public static boolean isNumeric(String inputData) {
Scanner sc = new Scanner(inputData);
return sc.hasNextInt();
}
Saya memodifikasi solusi CraigTP untuk menerima notasi ilmiah dan juga titik dan koma sebagai pemisah desimal
^-?\d+([,\.]\d+)?([eE]-?\d+)?$
contoh
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
Itu sebabnya saya menyukai pendekatan Try * di .NET. Selain metode Parse tradisional yang seperti Java, Anda juga memiliki metode TryParse. Saya tidak pandai sintaksis Java (parameter out?), Jadi tolong perlakukan yang berikut ini sebagai semacam pseudo-code. Seharusnya konsepnya jelas.
boolean parseInteger(String s, out int number)
{
try {
number = Integer.parseInt(myString);
return true;
} catch(NumberFormatException e) {
return false;
}
}
Pemakaian:
int num;
if (parseInteger("23", out num)) {
// Do something with num.
}
Parse itu (yaitu dengan Integer#parseInt
) dan cukup menangkap pengecualian. =)
Untuk memperjelas: Fungsi parseInt memeriksa apakah ia dapat menguraikan nomor dalam kasus apa pun (jelas) dan jika Anda tetap ingin menguraikannya, Anda tidak akan mendapatkan kinerja yang terpukul dengan benar-benar melakukan parsing.
Jika Anda tidak ingin menguraikannya (atau menguraikannya sangat, sangat jarang), Anda tentu ingin melakukannya secara berbeda.
Anda dapat menggunakan NumberUtils.isCreatable () dari Apache Commons Lang .
Karena NumberUtils.isNumber akan ditinggalkan pada 4.0, jadi gunakan NumberUtils.isCreatable () sebagai gantinya.
Java 8 Stream, ekspresi lambda, antarmuka fungsional
Semua kasus ditangani ( string null, string kosong dll )
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();
Saya telah menggambarkan beberapa kondisi untuk memeriksa angka dan desimal tanpa menggunakan API apa pun,
Periksa Perbaiki Panjang 1 digit angka
Character.isDigit(char)
Periksa nomor Fix Length (Asumsikan panjang 6)
String number = "132452";
if(number.matches("([0-9]{6})"))
System.out.println("6 digits number identified");
Periksa nomor Panjang yang Bervariasi antara (Asumsikan panjang 4 hingga 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");
Periksa Memvariasikan angka desimal Panjang antara (Asumsikan 4 hingga 7 panjang)
// 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");
Semoga ini bisa membantu orang lain.
Didasarkan atas jawaban lain saya menulis sendiri dan tidak menggunakan pola atau parsing dengan pengecekan pengecualian.
Ia memeriksa maksimum satu tanda minus dan memeriksa maksimum satu titik desimal.
Berikut ini beberapa contoh dan hasilnya:
"1", "-1", "-1.5" dan "-1.556" mengembalikan true
"1..5", "1A.5", "1.5D", "-" dan "--1" menghasilkan false
Catatan: Jika perlu, Anda dapat memodifikasi ini untuk menerima parameter Lokal dan meneruskannya ke panggilan DecimalFormatSymbols.getInstance () untuk menggunakan Lokal tertentu alih-alih yang sekarang.
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;
}
Berikut adalah dua metode yang mungkin berhasil. (Tanpa menggunakan Pengecualian). Catatan: Java adalah nilai pass-by-nilai secara default dan nilai String adalah alamat data objek String. Jadi, ketika Anda melakukannya
stringNumber = stringNumber.replaceAll(" ", "");
Anda telah mengubah nilai input menjadi tidak ada spasi. Anda dapat menghapus garis itu jika mau.
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;
}
Berikut adalah metode lain jika Anda ingin mengizinkan pelampung. Metode ini diduga memungkinkan angka-angka dalam bentuk lulus 1.123,123,123,123,123,123.123 saya baru saja membuatnya, dan saya pikir perlu pengujian lebih lanjut untuk memastikannya berfungsi.
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;
}