Bagaimana untuk memeriksa apakah String numerik di Jawa

Bagaimana anda akan memeriksa apakah String adalah angka sebelum parsing itu?

Mengomentari pertanyaan (6)

Hal ini umumnya dilakukan dengan sederhana user-defined function (yaitu Roll-anda-sendiri "isNumeric" fungsi).

Sesuatu seperti:

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

Namun, jika anda're memanggil fungsi ini banyak, dan anda mengharapkan banyak dari pemeriksaan gagal karena tidak menjadi nomor maka kinerja dari mekanisme ini tidak akan menjadi besar, karena anda're mengandalkan pengecualian dilemparkan untuk setiap kegagalan yang cukup mahal operasi.

Alternatif pendekatan yang mungkin untuk 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.
}

Hati-hati dengan RegEx di atas mekanisme, meskipun, karena itu akan gagal jika anda're menggunakan non-arab digit (yaitu angka selain 0 sampai 9). Hal ini karena "\d" bagian dari RegEx yang hanya akan pertandingan [0-9] dan efektif isn't internasional numerik sadar. (Terima kasih untuk OregonGhost untuk menunjukkan ini!)

Atau bahkan alternatif lain adalah dengan menggunakan Java's built-in java.teks.NumberFormat objek untuk melihat jika, setelah parsing string parser posisi di akhir string. Jika sudah, kita dapat mengasumsikan seluruh string 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();
}
Komentar (24)
Larutan

Dengan Apache Commons Lang 3.5 dan di atas: 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 untuk string kosong dan mengabaikan internal spasi dalam string. Cara lain adalah dengan menggunakan StringUtils.isParsable yang pada dasarnya pemeriksaan jumlah ini dapat diuraikan menurut Jawa. (Terkait javadocs mengandung detil contoh-contoh untuk masing-masing metode.)

Komentar (13)

jika anda berada di android, maka anda harus menggunakan:

android.text.TextUtils.isDigitsOnly(CharSequence str)

dokumentasi dapat ditemukan di sini

keep it simple. sebagian besar orang dapat "re-program" (hal yang sama).

Komentar (5)

Seperti @CraigTP telah disebutkan dalam jawaban yang sangat baik, saya juga memiliki kinerja yang sama menyangkut menggunakan Pengecualian untuk menguji apakah string numerik atau tidak. Jadi saya akhirnya membelah string dan menggunakan jawa.lang.Karakter.isDigit().

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

Menurut Awal, Karakter.isDigit(char) dengan benar akan mengakui non-Latin digit. Kinerja-bijaksana, saya pikir yang sederhana N jumlah perbandingan di mana N adalah jumlah karakter dalam string akan lebih komputasi efisien daripada melakukan regex yang cocok.

UPDATE: Seperti yang ditunjukkan oleh Jean-François Corbett di komentar, kode di atas hanya akan memvalidasi bilangan bulat positif, yang mencakup sebagian besar saya gunakan kasus. Di bawah ini adalah update kode yang benar memvalidasi angka desimal sesuai dengan standar lokal yang digunakan di sistem anda, dengan asumsi bahwa pemisah desimal hanya terjadi sekali 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;
}
Komentar (7)

Jawa 8 ekspresi lambda.

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

Google's Jambu perpustakaan menyediakan baik penolong metode untuk melakukan hal ini: Int.tryParse. Anda menggunakannya seperti Integer.parseInt tapi itu kembali null daripada melempar Pengecualian jika string tidak mengurai ke integer yang valid. Perhatikan bahwa ia mengembalikan Integer, tidak int, jadi anda harus mengkonversi/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, seperti dari rilis saat ini -- Jambu r11 -- itu masih ditandai @Beta.

Aku ingin't diperbandingkan itu. Melihat kode sumber ada beberapa overhead dari banyak kewarasan memeriksa tetapi pada akhirnya mereka menggunakan Karakter.digit(string.charAt(idx)), yang mirip, tapi sedikit berbeda dari, jawaban dari @Ibrahim di atas. Tidak ada pengecualian penanganan overhead bawah selimut dalam pelaksanaannya.

Komentar (1)

Jangan menggunakan Pengecualian untuk memvalidasi nilai-nilai anda. Gunakan Util libs bukan seperti apache NumberUtils:

NumberUtils.isNumber(myStringValue);

Edit:

Harap perhatikan bahwa, jika string dimulai dengan 0, NumberUtils akan menafsirkan nilai sebagai heksadesimal.

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

Mengapa semua orang mendorong untuk pengecualian/regex solusi?

Sementara aku dapat memahami sebagian besar orang baik-baik saja dengan menggunakan try/catch, jika anda ingin melakukannya sering... itu bisa sangat melelahkan.

Apa yang saya lakukan di sini adalah mengambil regex, yang parseNumber() metode, dan array mencari metode untuk melihat yang 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  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 punya 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

Disclaimer: saya'm tidak mengklaim metode ini 100% dioptimalkan, mereka're hanya untuk demonstrasi data

Pengecualian tidak jika dan hanya jika nomor 4 karakter atau kurang, dan setiap string selalu nomor... dalam hal ini, mengapa bahkan memiliki cek?

Dalam jangka pendek, hal ini sangat menyakitkan jika anda menjalankan ke nomor tidak valid sering dengan mencoba menangkap, yang masuk akal. Aturan penting yang selalu saya ikuti adalah jangan PERNAH menggunakan try/catch untuk alur program. Ini adalah contoh mengapa.

Menariknya, sederhana jika char <0 || >9 sangat sederhana untuk menulis, mudah untuk diingat (dan harus bekerja dalam beberapa bahasa) dan berhasil merebut hampir semua skenario pengujian.

Satu-satunya downside adalah bahwa saya'm menebak bilangan Bulat.parseInt() akan menangani non-ASCII angka, sedangkan array mencari metode tidak.


Bagi mereka bertanya-tanya mengapa aku mengatakan itu's mudah untuk mengingat karakter array satu, jika anda tahu ada's tidak ada tanda-tanda negatif, anda dapat dengan mudah pergi 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 akhir, saya ingin tahu tentang assigment operator di diterima misalnya dengan semua suara hingga. Menambahkan dalam tugas

double d = Double.parseDouble(...)

tidak hanya berguna karena anda don't bahkan menggunakan nilai, tetapi limbah pengolahan waktu dan meningkatkan runtime oleh beberapa nanodetik (yang menyebabkan 100-200 ms peningkatan dalam tes). Saya dapat't melihat mengapa seseorang tidak akan melakukan itu karena itu benar-benar bekerja ekstra untuk mengurangi kinerja.

Anda'd pikir itu akan dioptimalkan keluar... meskipun mungkin aku harus memeriksa bytecode dan melihat apa yang penyusun lakukan. Itu doesn't menjelaskan mengapa hal itu selalu muncul sebagai lebih panjang bagi saya meskipun jika entah bagaimana dioptimalkan keluar... oleh karena itu saya bertanya-tanya apa yang's terjadi. Sebagai catatan: Dengan lebih panjang, maksud saya menjalankan tes untuk 10000000 iterasi, dan menjalankan program itu beberapa kali (10x+) selalu menunjukkan untuk menjadi lebih lambat.

EDIT: Diperbarui tes untuk Karakter.isDigit()

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

CraigTP's regular expression (ditampilkan di atas) menghasilkan positif palsu. E. g. "23y4" akan dihitung sebagai jumlah karena '.' cocok dengan semua karakter yang bukan titik desimal.

Juga akan menolak setiap nomor dengan terkemuka '+'

Alternatif yang menghindari dua masalah kecil adalah

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

Kita dapat mencoba mengganti semua angka dari string tertentu dengan ("") yaitu ruang kosong dan jika setelah itu panjang dari string adalah nol, maka kita dapat mengatakan bahwa mengingat string hanya berisi angka-angka. [Jika anda menemukan jawaban ini bermanfaat maka jangan menganggap pemungutan suara itu] 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;
    }
Komentar (1)

Anda dapat menggunakan NumberFormat#parse:

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

Jika anda menggunakan java untuk mengembangkan aplikasi Android, anda bisa menggunakan TextUtils.isDigitsOnly fungsi.

Komentar (0)

Berikut ini adalah jawaban saya untuk masalah ini.

Menangkap semua kemudahan metode yang dapat anda gunakan untuk mengurai String apapun dengan setiap jenis parser: isParsable(Objek parser, String str). Parser dapat menjadi Kelas atau objek. Ini juga akan memungkinkan anda untuk menggunakan kustom parser anda've tertulis dan harus bekerja untuk selama-lamanya skenario, 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");

Berikut ini's my kode lengkap dengan metode deskripsi.

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;
    }
}
Komentar (0)

Pengecualian adalah mahal, tetapi dalam kasus ini RegEx memakan waktu lebih lama. Kode di bawah ini menunjukkan sebuah tes sederhana dari dua fungsi -- satu menggunakan pengecualian dan satu menggunakan regex. Pada mesin RegEx versi 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
Komentar (2)

Regex yang Cocok

Berikut adalah contoh lain upgrade "CraigTP" regex yang cocok dengan lebih validasi.

public static boolean isNumeric(String str)
{
    return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
  1. Hanya satu tanda negatif - diperbolehkan dan harus di awal.
  2. Setelah tanda negatif harus ada digit.
  3. Hanya satu tanda desimal . diperbolehkan.
  4. Setelah tanda desimal harus ada digit.

Regex Tes

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
Komentar (0)

// silahkan cek di bawah kode

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;
}
Komentar (1)

Baik melakukan pendekatan menghindari coba-menangkap dan penanganan negatif angka 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();
}
Komentar (0)

Untuk pertandingan hanya positif base-sepuluh bilangan bulat, yang hanya berisi ASCII digit, gunakan:

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

Berikut adalah kelas saya untuk mengecek apakah suatu string numerik. Ini juga perbaikan numerik string:

Fitur:

  1. Menghilangkan yang tidak perlu nol ["12.0000000" -> "12"]
  2. Menghilangkan yang tidak perlu nol ["12.0580000" -> "12.058"]
  3. Menghilangkan non numerik karakter ["12.00sdfsdf00" -> "12"]
  4. Menangani negatif nilai string ["-12,020000" -> "-12.02"]
  5. Menghilangkan beberapa titik ["-12.0.20.000" -> "-12.02"]
  6. Tidak ada tambahan perpustakaan, hanya standar Java

Di sini anda pergi...

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

}
Komentar (0)

// only int
public static boolean isNumber(int num) 
{
    return (num >= 48 && c = '0' && c = '0' && c 
Komentar (0)