Qual è il modo migliore per verificare se una stringa rappresenta un numero intero in Java?


220

Normalmente utilizzo il seguente idioma per verificare se una stringa può essere convertita in un numero intero.

public boolean isInteger( String input ) {
    try {
        Integer.parseInt( input );
        return true;
    }
    catch( Exception e ) {
        return false;
    }
}

Sono solo io o sembra un po 'hacker? Qual è un modo migliore?


Vedi la mia risposta (con benchmark, basata sulla risposta precedente di CodingWithSpike ) per vedere perché ho invertito la mia posizione e accettato la risposta di Jonas Klemming a questo problema. Penso che questo codice originale verrà utilizzato dalla maggior parte delle persone perché è più veloce da implementare e più manutenibile, ma è più lento di ordini di grandezza quando vengono forniti dati non interi.


Qual è la tua idea di RegExp per la soluzione?
Akshay Pethani

Risposte:


173

Se non sei preoccupato per potenziali problemi di overflow, questa funzione funzionerà circa 20-30 volte più velocemente rispetto all'utilizzo Integer.parseInt().

public static boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    int length = str.length();
    if (length == 0) {
        return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
        if (length == 1) {
            return false;
        }
        i = 1;
    }
    for (; i < length; i++) {
        char c = str.charAt(i);
        if (c < '0' || c > '9') {
            return false;
        }
    }
    return true;
}

50
(c <= '/' || c> = ':') ha un aspetto un po 'strano. Avrei usato (c <'0' || c> '9') ... gli operatori <= e> = sono più veloci in Java?
Anonimo

3
Perché non usare regex? Return str.matches ("^ -? \\ d + $") non è identico al codice precedente.
Maglob

15
Userei questo metodo o il metodo originale dalla domanda prima dell'espressione regolare. Questo per le prestazioni, il metodo originale per la velocità di implementazione e la pura manutenibilità. La soluzione regex non ha nulla da offrire.
Bill the Lizard

4
Sono preoccupato per l'overflow, ma questo metodo può essere adattato per BigInts ed essere ancora molto più veloce di altri metodi. Nel caso qualcuno si chieda perché sto mettendo così tanto impegno in un problema così semplice, sto creando una libreria per aiutare a risolvere i problemi del Progetto Eulero.
Bill the Lizard

2
Se sei preoccupato se puoi effettivamente analizzare la stringa in un int o in un lungo, dovresti anche controllare se il numero intero rappresentato dalla stringa si adatta effettivamente a quei tipi di dati.
Jonas K

65

Ce l'hai, ma dovresti solo prendere NumberFormatException.


7
Sì, è considerato una cattiva forma catturare più eccezioni del necessario.
Chris,

Hai ragione. La NFE è l'unica che può essere lanciata, ma è comunque una cattiva abitudine da prendere.
Bill the Lizard

Penso che un NPE possa essere lanciato se l'input è nullo, quindi il tuo metodo dovrebbe probabilmente gestirlo in modo esplicito, in qualsiasi modo tu voglia.
Dov Wasserman

@Dov: hai ragione NPE e NFE dovrebbero essere entrambi esplicitamente catturati.
Bill the Lizard,

Questa risposta dovrebbe essere la vera risposta a questa domanda.
Breedly

40

Ha fatto un rapido benchmark. Le eccezioni non sono in realtà così costose, a meno che non si inizi a richiamare più metodi e la JVM deve fare molto lavoro per ottenere lo stack di esecuzione in atto. Quando rimangono nello stesso metodo, non sono cattivi interpreti.

 public void RunTests()
 {
     String str = "1234567890";

     long startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByException(str);
     long endTime = System.currentTimeMillis();
     System.out.print("ByException: ");
     System.out.println(endTime - startTime);

     startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByRegex(str);
     endTime = System.currentTimeMillis();
     System.out.print("ByRegex: ");
     System.out.println(endTime - startTime);

     startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByJonas(str);
     endTime = System.currentTimeMillis();
     System.out.print("ByJonas: ");
     System.out.println(endTime - startTime);
 }

 private boolean IsInt_ByException(String str)
 {
     try
     {
         Integer.parseInt(str);
         return true;
     }
     catch(NumberFormatException nfe)
     {
         return false;
     }
 }

 private boolean IsInt_ByRegex(String str)
 {
     return str.matches("^-?\\d+$");
 }

 public boolean IsInt_ByJonas(String str)
 {
     if (str == null) {
             return false;
     }
     int length = str.length();
     if (length == 0) {
             return false;
     }
     int i = 0;
     if (str.charAt(0) == '-') {
             if (length == 1) {
                     return false;
             }
             i = 1;
     }
     for (; i < length; i++) {
             char c = str.charAt(i);
             if (c <= '/' || c >= ':') {
                     return false;
             }
     }
     return true;
 }

Produzione:

ByException: 31

ByRegex: 453 (nota: ricompilazione del modello ogni volta)

DiJonas: 16

Sono d'accordo che la soluzione di Jonas K sia anche la più robusta. Sembra che vinca :)


13
Ottima idea per confrontare tutti e tre. Per essere onesti con i metodi Regex e Jonas, dovresti testare con stringhe non intere, poiché è lì che il metodo Integer.parseInt rallenterà davvero.
Bill the Lizard il

4
Siamo spiacenti ma questo test regex non è buono. (1) Non è necessario eseguire il controllo del motore regex ^e la $seconda volta poiché l' matchesintera stringa deve corrispondere all'espressione regolare, (2) str.matchesogni volta dovrà crearne una propria Patternche è costosa. Per motivi di prestazioni dovremmo creare tale Pattern solo una volta al di fuori di questo metodo e usarlo all'interno. (3) Possiamo anche creare un solo oggetto Matcher e usarlo reset(CharSequence)per passare i dati dell'utente e restituirne il matches()risultato.
Pshemo

Quindi qualcosa di simile private final Matcher m = Pattern.compile("-?\\d+").matcher(""); private boolean byRegex(String str) { return m.reset(str).matches(); }dovrebbe avere prestazioni migliori.
Pshemo

@Pshemo Integer.valueOf ("1") e Integer.valueOf ("1") generano entrambi un'eccezione, quindi controllare ^ e $ sembra ragionevole.
cquezel

1
@cquezel Sì, ma non è richiesto poiché matchesaggiunge ^e $implicitamente. Dai un'occhiata al risultato di " 123".matches("\\d+")e "123".matches("\\d+"). Vedrai falsee true. falseverrà restituito perché la stringa inizia con uno spazio che impedisce che venga interamente trovata dalla regex.
Pshemo

37

Dato che c'è la possibilità che le persone visitino ancora qui e saranno prevenute contro Regex dopo i benchmark ... Quindi darò una versione aggiornata del benchmark, con una versione compilata del Regex. A differenza dei benchmark precedenti, questo mostra che la soluzione Regex ha effettivamente prestazioni costantemente buone.

Copiato da Bill the Lizard e aggiornato con la versione compilata:

private final Pattern pattern = Pattern.compile("^-?\\d+$");

public void runTests() {
    String big_int = "1234567890";
    String non_int = "1234XY7890";

    long startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByException(big_int);
    long endTime = System.currentTimeMillis();
    System.out.print("ByException - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByException(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByException - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByRegex - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
            IsInt_ByCompiledRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByCompiledRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
            IsInt_ByCompiledRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByCompiledRegex - non-integer data: ");
    System.out.println(endTime - startTime);


    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByJonas(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByJonas - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByJonas(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByJonas - non-integer data: ");
    System.out.println(endTime - startTime);
}

private boolean IsInt_ByException(String str)
{
    try
    {
        Integer.parseInt(str);
        return true;
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
}

private boolean IsInt_ByRegex(String str)
{
    return str.matches("^-?\\d+$");
}

private boolean IsInt_ByCompiledRegex(String str) {
    return pattern.matcher(str).find();
}

public boolean IsInt_ByJonas(String str)
{
    if (str == null) {
            return false;
    }
    int length = str.length();
    if (length == 0) {
            return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
            if (length == 1) {
                    return false;
            }
            i = 1;
    }
    for (; i < length; i++) {
            char c = str.charAt(i);
            if (c <= '/' || c >= ':') {
                    return false;
            }
    }
    return true;
}

Risultati:

ByException - integer data: 45
ByException - non-integer data: 465

ByRegex - integer data: 272
ByRegex - non-integer data: 131

ByCompiledRegex - integer data: 45
ByCompiledRegex - non-integer data: 26

ByJonas - integer data: 8
ByJonas - non-integer data: 2

1
Il tempo ByCompiledRegex deve includere la compilazione della regex nella sua misurazione del tempo.
Martin Carney

2
@MartinCarney L'ho modificato e ho confrontato la compilazione del pattern. Ovviamente la mia CPU / JIT è più veloce, ma se la interpolo di nuovo, il tempo di compilazione è 336.
tedder42

2
per essere chiari, 336 (ms) è ciò che accade quando la compilazione del pattern viene eseguita 100k volte, proprio come tutte le altre righe. Con l'implicazione che viene eseguito solo una volta, il suo tempo è praticamente zero.
Voltafieno42

Grazie per aver impostato il record direttamente sui tempi di regex compilati.
LarsH

Forse "^[+-]?\\d+$"sarebbe anche meglio.
Adam

34
org.apache.commons.lang.StringUtils.isNumeric 

sebbene la libreria standard di Java manchi davvero di tali funzioni di utilità

Penso che Apache Commons sia un "must have" per ogni programmatore Java

peccato che non sia ancora stato portato su Java5


1
L'unico problema con questo è l'overflow: SI ti dà ancora +1 per menzionare commons-lang :)
javamonkey79

2
L'altro problema sono i numeri negativi, ma ho anche +1, poiché a mio avviso questo approccio si avvicina di più a una buona soluzione.
sandris

23

In parte dipende da cosa intendi per "può essere convertito in un numero intero".

Se intendi "può essere convertito in un int in Java", la risposta di Jonas è un buon inizio, ma non completa il lavoro. Ad esempio, passerebbe 999999999999999999999999999999. Aggiungerei la normale chiamata try / catch dalla tua stessa domanda alla fine del metodo.

I controlli carattere per carattere rifiuteranno efficacemente i casi "non è affatto un intero", lasciando che i casi "è un numero intero ma Java non può gestirlo" vengano catturati dalla rotta di eccezione più lenta. Si potrebbe fare questo a poco a mano troppo, ma sarebbe un molto più complicato.


18

Solo un commento su regexp. Ogni esempio fornito qui è sbagliato !. Se vuoi usare regexp non dimenticare che la compilazione del pattern richiede molto tempo. Questo:

str.matches("^-?\\d+$")

e anche questo:

Pattern.matches("-?\\d+", input);

causa la compilazione di pattern in ogni chiamata al metodo. Per usarlo correttamente seguire:

import java.util.regex.Pattern;

/**
 * @author Rastislav Komara
 */
public class NaturalNumberChecker {
    public static final Pattern PATTERN = Pattern.compile("^\\d+$");

    boolean isNaturalNumber(CharSequence input) {
        return input != null && PATTERN.matcher(input).matches();
    }
}

5
Puoi aumentare le prestazioni creando anche Matcher in anticipo e usando il suo metodo reset () per applicarlo all'input.
Alan Moore,

13

C'è la versione guava:

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);

Restituirà null invece di generare un'eccezione se non riesce ad analizzare la stringa.


3
Migliore risposta IMHO. Usa librerie ben testate invece di creare la tua soluzione. (Vedi anche la discussione qui .)
Olivier Cailloux

12

Ho copiato il codice dalla risposta di rally25rs e ho aggiunto alcuni test per dati non interi. I risultati sono innegabilmente favorevoli al metodo pubblicato da Jonas Klemming. I risultati per il metodo Eccezione che ho pubblicato originariamente sono abbastanza buoni quando hai dati interi, ma sono i peggiori quando non lo fai, mentre i risultati per la soluzione RegEx (che scommetto molte persone usano) erano costantemente cattivi. Vedi la risposta di Felipe per un esempio di regex compilato, che è molto più veloce.

public void runTests()
{
    String big_int = "1234567890";
    String non_int = "1234XY7890";

    long startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByException(big_int);
    long endTime = System.currentTimeMillis();
    System.out.print("ByException - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByException(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByException - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByRegex - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByJonas(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByJonas - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByJonas(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByJonas - non-integer data: ");
    System.out.println(endTime - startTime);
}

private boolean IsInt_ByException(String str)
{
    try
    {
        Integer.parseInt(str);
        return true;
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
}

private boolean IsInt_ByRegex(String str)
{
    return str.matches("^-?\\d+$");
}

public boolean IsInt_ByJonas(String str)
{
    if (str == null) {
            return false;
    }
    int length = str.length();
    if (length == 0) {
            return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
            if (length == 1) {
                    return false;
            }
            i = 1;
    }
    for (; i < length; i++) {
            char c = str.charAt(i);
            if (c <= '/' || c >= ':') {
                    return false;
            }
    }
    return true;
}

Risultati:

ByException - integer data: 47
ByException - non-integer data: 547

ByRegex - integer data: 390
ByRegex - non-integer data: 313

ByJonas - integer data: 0
ByJonas - non-integer data: 16

6

Questo è più breve, ma più corto non è necessariamente migliore (e non catturerà valori interi fuori intervallo, come sottolineato nel commento di danatel ):

input.matches("^-?\\d+$");

Personalmente, poiché l'implementazione è eliminata in un metodo di supporto e la correttezza ha la meglio sulla lunghezza, vorrei semplicemente andare con qualcosa di simile a quello che hai (meno la cattura della Exceptionclasse base piuttosto che NumberFormatException).


1
E forse \\ d {1,10} è, sebbene non perfetto, migliore di \\ d + per catturare
numeri

6

È possibile utilizzare il metodo match della classe string. Lo [0-9] rappresenta tutti i valori che può essere, il + significa che deve essere lungo almeno un carattere e * significa che può essere lungo zero o più caratteri.

boolean isNumeric = yourString.matches("[0-9]+"); // 1 or more characters long, numbers only
boolean isNumeric = yourString.matches("[0-9]*"); // 0 or more characters long, numbers only

1
Nb questo non corrisponde a "+10" o "-10"), che normalmente sarebbero inclusi come numeri interi validi
Tim Wintle

4

Che ne dite di:

return Pattern.matches("-?\\d+", input);

E il numero intero 9999999999999999999999999999999999?
Danatel

Non dimenticare di controllare il segno negativo.
Jeremy Ruten

non hai bisogno di ancorare l'inizio e la fine della regex, così non passerai "aaa-1999zzz"?
Tim Howland

2
Tim, quando chiami uno dei metodi match () (String, Pattern e Matcher ne hanno uno ciascuno), la regex deve corrispondere all'intero input, rendendo le ancore ridondanti. Per trovare una corrispondenza come definita dalla maggior parte delle altre versioni di espressioni regolari, devi usare Matcher # find ().
Alan Moore,

4

Questa è una variazione Java 8 della risposta di Jonas Klemming:

public static boolean isInteger(String str) {
    return str != null && str.length() > 0 &&
         IntStream.range(0, str.length()).allMatch(i -> i == 0 && (str.charAt(i) == '-' || str.charAt(i) == '+')
                  || Character.isDigit(str.charAt(i)));
}

Codice di prova:

public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    Arrays.asList("1231231", "-1232312312", "+12313123131", "qwqe123123211", "2", "0000000001111", "", "123-", "++123",
            "123-23", null, "+-123").forEach(s -> {
        System.out.printf("%15s %s%n", s, isInteger(s));
    });
}

Risultati del codice di prova:

        1231231 true
    -1232312312 true
   +12313123131 true
  qwqe123123211 false
              2 true
  0000000001111 true
                false
           123- false
          ++123 false
         123-23 false
           null false
          +-123 false

3

Devi solo controllare NumberFormatException : -

 String value="123";
 try  
 {  
    int s=Integer.parseInt(any_int_val);
    // do something when integer values comes 
 }  
 catch(NumberFormatException nfe)  
 {  
          // do something when string values comes 
 }  

3

Se l'array di stringhe contiene interi e stringhe puri, il codice seguente dovrebbe funzionare. Devi solo guardare il primo carattere. ad es. ["4", "44", "abc", "77", "bond"]

if (Character.isDigit(string.charAt(0))) {
    //Do something with int
}

3

Puoi anche usare la classe Scanner e usare hasNextInt () - e questo ti permette di testare anche altri tipi, come float, ecc.


Questa risposta mi ha dato un promemoria di cui avevo bisogno. Mi ero completamente dimenticato che Scanner aveva una tale funzione. T-up
Hubro

2

Se vuoi controllare se la stringa rappresenta un numero intero che si adatta a un tipo int, ho apportato una piccola modifica alla risposta di jonas, in modo che le stringhe che rappresentano numeri interi più grandi di Integer.MAX_VALUE o più piccoli di Integer.MIN_VALUE, ora torneranno falso. Ad esempio: "3147483647" restituirà false perché 3147483647 è maggiore di 2147483647 e, allo stesso modo, "-2147483649" restituirà false perché -2147483649 è minore di -2147483648.

public static boolean isInt(String s) {
  if(s == null) {
    return false;
  }
  s = s.trim(); //Don't get tricked by whitespaces.
  int len = s.length();
  if(len == 0) {
    return false;
  }
  //The bottom limit of an int is -2147483648 which is 11 chars long.
  //[note that the upper limit (2147483647) is only 10 chars long]
  //Thus any string with more than 11 chars, even if represents a valid integer, 
  //it won't fit in an int.
  if(len > 11) {
    return false;
  }
  char c = s.charAt(0);
  int i = 0;
  //I don't mind the plus sign, so "+13" will return true.
  if(c == '-' || c == '+') {
    //A single "+" or "-" is not a valid integer.
    if(len == 1) {
      return false;
    }
    i = 1;
  }
  //Check if all chars are digits
  for(; i < len; i++) {
    c = s.charAt(i);
    if(c < '0' || c > '9') {
      return false;
    }
  }
  //If we reached this point then we know for sure that the string has at
  //most 11 chars and that they're all digits (the first one might be a '+'
  // or '-' thought).
  //Now we just need to check, for 10 and 11 chars long strings, if the numbers
  //represented by the them don't surpass the limits.
  c = s.charAt(0);
  char l;
  String limit;
  if(len == 10 && c != '-' && c != '+') {
    limit = "2147483647";
    //Now we are going to compare each char of the string with the char in
    //the limit string that has the same index, so if the string is "ABC" and
    //the limit string is "DEF" then we are gonna compare A to D, B to E and so on.
    //c is the current string's char and l is the corresponding limit's char
    //Note that the loop only continues if c == l. Now imagine that our string
    //is "2150000000", 2 == 2 (next), 1 == 1 (next), 5 > 4 as you can see,
    //because 5 > 4 we can guarantee that the string will represent a bigger integer.
    //Similarly, if our string was "2139999999", when we find out that 3 < 4,
    //we can also guarantee that the integer represented will fit in an int.
    for(i = 0; i < len; i++) {
      c = s.charAt(i);
      l = limit.charAt(i);
      if(c > l) {
        return false;
      }
      if(c < l) {
        return true;
      }
    }
  }
  c = s.charAt(0);
  if(len == 11) {
    //If the first char is neither '+' nor '-' then 11 digits represent a 
    //bigger integer than 2147483647 (10 digits).
    if(c != '+' && c != '-') {
      return false;
    }
    limit = (c == '-') ? "-2147483648" : "+2147483647";
    //Here we're applying the same logic that we applied in the previous case
    //ignoring the first char.
    for(i = 1; i < len; i++) {
      c = s.charAt(i);
      l = limit.charAt(i);
      if(c > l) {
        return false;
      }
      if(c < l) {
        return true;
      }
    }
  }
  //The string passed all tests, so it must represent a number that fits
  //in an int...
  return true;
}

1
puoi modificare la tua risposta e spiegare come migliora la risposta precedente che hai menzionato?
Gilles Gouaillardet

Grazie per la magnifica risposta. Ma "123" cioè 123 insieme allo spazio è considerato come numero intero valido.
Saikrishna Radarapu

1
@SaikrishnaRadarapu Usano trim()quindi questa è chiaramente una scelta di design intenzionale.
Guildenstern,


1

Probabilmente devi tenere in considerazione anche il caso d'uso:

Se la maggior parte delle volte ti aspetti che i numeri siano validi, il rilevamento dell'eccezione causa solo un sovraccarico delle prestazioni quando si tenta di convertire i numeri non validi. Considerando che la chiamata di un isInteger()metodo e quindi la conversione utilizzando Integer.parseInt()causerà sempre un sovraccarico delle prestazioni per i numeri validi: le stringhe vengono analizzate due volte, una volta dal controllo e una volta dalla conversione.


1

Questa è una modifica del codice di Jonas che controlla se la stringa rientra nell'intervallo per essere convertita in un numero intero.

public static boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    int length = str.length();
    int i = 0;

    // set the length and value for highest positive int or lowest negative int
    int maxlength = 10;
    String maxnum = String.valueOf(Integer.MAX_VALUE);
    if (str.charAt(0) == '-') { 
        maxlength = 11;
        i = 1;
        maxnum = String.valueOf(Integer.MIN_VALUE);
    }  

    // verify digit length does not exceed int range
    if (length > maxlength) { 
        return false; 
    }

    // verify that all characters are numbers
    if (maxlength == 11 && length == 1) {
        return false;
    }
    for (int num = i; num < length; num++) {
        char c = str.charAt(num);
        if (c < '0' || c > '9') {
            return false;
        }
    }

    // verify that number value is within int range
    if (length == maxlength) {
        for (; i < length; i++) {
            if (str.charAt(i) < maxnum.charAt(i)) {
                return true;
            }
            else if (str.charAt(i) > maxnum.charAt(i)) {
                return false;
            }
        }
    }
    return true;
}

1
sembra buono, ma l'ultimo ciclo for deve essere reimpostato a zero (o 1 se un numero negativo) perché il ciclo che controlla se ogni cifra è un numero risulterà che io sia la lunghezza della stringa, quindi l'ultimo ciclo for non correrà mai. Vorrei anche utilizzare le costanti Java Integer.MAX_VALUE e Integer.MIN_VALUE invece dei numeri magici.
Tim the Enchanter,

@TimtheEnchanter Grazie per i suggerimenti, li ho completamente trascurati. Nella mia modifica per incorporarli ho usato una nuova variabile nel primo ciclo for per evitare l'istruzione if aggiuntiva.
Wayne

1

Se stai usando l'API Android puoi usare:

TextUtils.isDigitsOnly(str);

1

Credo che ci sia il rischio zero incorrere in un'eccezione, perché come si può vedere qui sotto sempre analizzare in modo sicuro intal Stringe non il contrario.

Così:

  1. È controllare se ogni fessura di carattere nella stringa di partite almeno uno dei personaggi { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} .

    if(aString.substring(j, j+1).equals(String.valueOf(i)))
    
  2. Si somma tutte le volte che hai incontrato negli slot dei personaggi di cui sopra.

    digits++;
    
  3. E infine controlli se le volte in cui hai incontrato interi come caratteri sono uguali alla lunghezza della stringa data.

    if(digits == aString.length())
    

E in pratica abbiamo:

    String aString = "1234224245";
    int digits = 0;//count how many digits you encountered
    for(int j=0;j<aString.length();j++){
        for(int i=0;i<=9;i++){
            if(aString.substring(j, j+1).equals(String.valueOf(i)))
                    digits++;
        }
    }
    if(digits == aString.length()){
        System.out.println("It's an integer!!");
        }
    else{
        System.out.println("It's not an integer!!");
    }
    
    String anotherString = "1234f22a4245";
    int anotherDigits = 0;//count how many digits you encountered
    for(int j=0;j<anotherString.length();j++){
        for(int i=0;i<=9;i++){
            if(anotherString.substring(j, j+1).equals(String.valueOf(i)))
                    anotherDigits++;
        }
    }
    if(anotherDigits == anotherString.length()){
        System.out.println("It's an integer!!");
        }
    else{
        System.out.println("It's not an integer!!");
    }

E i risultati sono:

È un numero intero !!

Non è un numero intero !!

Allo stesso modo, puoi convalidare se a Stringè a floato a, doublema in quei casi devi incontrarne solo uno. (punto) nella stringa e ovviamente controlla se digits == (aString.length()-1)

Di nuovo, non c'è rischio di incorrere in un'eccezione di analisi qui, ma se prevedi di analizzare una stringa che è nota che contiene un numero (diciamo tipo di dati int ) devi prima controllare se si adatta al tipo di dati. Altrimenti devi lanciarlo.

Spero di aver aiutato


1

Un'altra opzione:

private boolean isNumber(String s) {
    boolean isNumber = true;
    for (char c : s.toCharArray()) {
        isNumber = isNumber && Character.isDigit(c);
    }
    return isNumber;
}

0
is_number = true;
try {
  Integer.parseInt(mystr)
} catch (NumberFormatException  e) {
  is_number = false;
}

5
Questo sta facendo esattamente la stessa cosa di cui chiede il poster.
Martin Carney

0

Quello che hai fatto funziona, ma probabilmente non dovresti sempre controllare in questo modo. Le eccezioni dovrebbero essere riservate a situazioni "eccezionali" (forse questo si adatta al tuo caso, però) e sono molto costose in termini di prestazioni.


Sono costosi solo se vengono lanciati.
Bill the Lizard,

0
Number number;
try {
    number = NumberFormat.getInstance().parse("123");
} catch (ParseException e) {
    //not a number - do recovery.
    e.printStackTrace();
}
//use number

0

Questo funzionerebbe solo per numeri interi positivi.

public static boolean isInt(String str) {
    if (str != null && str.length() != 0) {
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) return false;
        }
    }
    return true;        
}

4
Benvenuto in stackoverflow. Prima di resuscitare un vecchio thread assicurati di leggere le risposte e i commenti precedenti. Questo metodo (e gli eventuali svantaggi) sono stati effettivamente già discussi.
Leigh

0

Questo funziona per me. Semplicemente per identificare se una stringa è una primitiva o un numero.

private boolean isPrimitive(String value){
        boolean status=true;
        if(value.length()<1)
            return false;
        for(int i = 0;i<value.length();i++){
            char c=value.charAt(i);
            if(Character.isDigit(c) || c=='.'){

            }else{
                status=false;
                break;
            }
        }
        return status;
    }

0

Per controllare tutti i caratteri int, puoi semplicemente usare un doppio negativo.

if (! searchString.matches ("[^ 0-9] + $")) ...

[^ 0-9] + $ controlla se ci sono caratteri che non sono interi, quindi il test fallisce se è vero. Solo NON quello e diventi vero con il successo.


No. Chiaramente non l'hai testato. Restituisce vero solo se c'è una cifra da qualche parte nella stringa, non se la stringa è composta da sole cifre. Il matchesmetodo confronta l'intera stringa, non solo una parte di essa.
Dawood ibn Kareem

Non ottieni la doppia parte negativa.
Roger F. Gay

Beh, NON ottengo il doppio negativo. Questo semplicemente non funziona. Se hai un misto di cifre e lettere, questo va nel ifblocco. Non dovrebbe.
Dawood ibn Kareem

0

Trova questo può essere utile:

public static boolean isInteger(String self) {
    try {
        Integer.valueOf(self.trim());
        return true;
    } catch (NumberFormatException nfe) {
        return false;
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.