2009-07-22 13 views
8

Sto cercando un metodo che restituisce un valore booleano se la stringa passata è un numero valido (ad esempio "123.55e-9", "-333.556 "). Io Non vogliono fare proprio:Libreria Java per verificare se una stringa contiene un numero * senza * eccezioni

public boolean isANumber(String s) { 
    try { 
     BigDecimal a = new BigDecimal(s); 
     return true; 
    } catch (NumberFormatException e) { 
     return false; 
    } 
} 

Chiaramente, la funzione dovrebbe utilizzare una macchina a stati (DFA) per analizzare la stringa per assicurarsi che non validi esempi non ingannare esso (ad esempio "-21, 22.22.2 "," 33-2 "). Sai se esiste una biblioteca del genere? Non voglio davvero scriverlo da solo perché è un problema così ovvio che sono sicuro che reinventerò la ruota.

Grazie,

Nick

+0

Perché proprio non vuoi usare l'analisi da BigDecimal? È il modo più semplice, davvero. – Jorn

+0

Mi piacerebbe sapere perché non vuoi usare lo snippet che hai fornito? Se hai bisogno di _use_ il numero devi analizzarlo? È solo per verificare che una stringa possa andare al back-end così com'è? –

+0

Perché le eccezioni non sono valide per questo caso. Le eccezioni sono, beh, per le eccezioni non per il controllo del programma. – Malax

risposta

6

I Eviterei di reinventare questo metodo e andare con Apache Commons. Se usi Spring, Struts o molte altre librerie java di uso comune, spesso includono i comuni Apache. Vorresti il ​​file commons-lang.jar. Ecco il metodo in NumberUtils si vorrebbe:

isNumber[1] 

public static boolean isNumber(java.lang.String str) 
Checks whether the String a valid Java number. 

Valid numbers include hexadecimal marked with the 0x qualifier, scientific notation and numbers marked with a type qualifier (e.g. 123L). 

Null and empty String will return false. 

Parameters: 
str - the String to check 
Returns: 
true if the string is a correctly formatted number 
3

utilizzare un regexp

+0

esattamente. e qui http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html#BigDecimal(java.lang.String) avete del cibo per i vostri test unitari. – flybywire

+0

+1 dato che Commons-Lang non offre questo – skaffman

+0

Grazie per avermi segnalato a commons-lang. roba ordinata! – Malax

2

Sì un'espressione regolare dovrebbe fare il trucco. So solo regexp .Net, ma tutte le lingue regex sono abbastanza simili, quindi questo dovrebbe iniziare. Non l'ho provato, quindi potresti voler dare un calcio con la classe regex di Java.

"-?(([0-9]{1,3}(,[0-9{3,3})*)|[0-9]*)(\.[0-9]+(e-?[0-9]*)?)?" 

Alcuni della sintassi di controllo Regex:
? - Elemento facoltativo
| - Operatore OR. Fondamentalmente ho permesso numeri con o senza virgole se fossero stati formattati correttamente.
[] - Set di caratteri consentiti
{,} - massima minima del elemento
* - Qualsiasi numero di elementi, 0 a infinito
+ - almeno un elemento, 1 a infinito
\ - Escape carattere
. - Qualsiasi carattere (Da qui il motivo per cui si è sfuggito)

+0

+1 per l'effettiva implementazione – dfa

+0

questa espressione corrisponderà a 22,22,2,14123415e1 – Salandur

+0

e non corrisponderà a 1e-1. – Bombe

2

Ecco una funzione di utilità regexp basato funzionare bene (non ha potuto montare il "" check-in l'espressione regolare, mantenendo leggibile):

public class TestRegexp { 
    static final String NUM_REGEX= 
     "-?((([0-9]{1,3})(,[0-9]{3})*)|[0-9]*)(\\.[0-9]+)?([Ee][0-9]*)?"; 
    public static boolean isNum(String s) { 
      return s!=null && s.length()>0 && s.matches(NUM_REGEX); 
    } 
    public static void main(String[]args) { 
     String[] values={ 
       "", 
       "0", 
       "0.1", 
       ".1", 
       "-.5E5", 
       "-12,524.5E5", 
       "-452,456,456,466.5E5", 
       "-452,456,456,466E5", 
       "22,22,2.14123415e1", 
     }; 
     for (String value : values) { 
      System.out.println(value+" is a number: " 
      +isNum(value)); 
     } 
    } 

} 
2

L'esatta espressione regolare è specificato nella Javadocs per Double.valueOf(String).

Per evitare di chiamare questo metodo su una stringa non valida e che abbia un NumberFormatException essere gettati, l'espressione regolare di seguito può essere utilizzato per lo screening la stringa di input:

final String Digits  = "(\\p{Digit}+)"; 
final String HexDigits = "(\\p{XDigit}+)"; 
// an exponent is 'e' or 'E' followed by an optionally 
// signed decimal integer. 
final String Exp  = "[eE][+-]?"+Digits; 
final String fpRegex = 
     ("[\\x00-\\x20]*"+ // Optional leading "whitespace" 
     "[+-]?(" + // Optional sign character 
     "NaN|" +   // "NaN" string 
     "Infinity|" +  // "Infinity" string 

     // A decimal floating-point string representing a finite positive 
     // number without a leading sign has at most five basic pieces: 
     // Digits . Digits ExponentPart FloatTypeSuffix 
     // 
     // Since this method allows integer-only strings as input 
     // in addition to strings of floating-point literals, the 
     // two sub-patterns below are simplifications of the grammar 
     // productions from the Java Language Specification, 2nd 
     // edition, section 3.10.2. 

     // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt 
     "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+ 

     // . Digits ExponentPart_opt FloatTypeSuffix_opt 
     "(\\.("+Digits+")("+Exp+")?)|"+ 

     // Hexadecimal strings 
     "((" + 
     // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt 
     "(0[xX]" + HexDigits + "(\\.)?)|" + 

     // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt 
     "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" + 

     ")[pP][+-]?" + Digits + "))" + 
     "[fFdD]?))" + 
     "[\\x00-\\x20]*"); // Optional trailing "whitespace" 

if (Pattern.matches(fpRegex, myString)) 
    Double.valueOf(myString); // Will not throw NumberFormatException 
else { 
    // Perform suitable alternative action 
} 
Problemi correlati