2009-07-22 5 views
8

Je cherche une méthode qui retourne un booléen si la chaîne est passée est un nombre valide (par exemple "123.55e-9", "-333 556 "). Je ne suis pas veulent simplement faire:Bibliothèque Java pour vérifier si une chaîne contient un nombre * sans * exceptions

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

De toute évidence, la fonction doit utiliser une machine d'état (DFA) pour analyser la chaîne pour faire des exemples sûrs invalides ne badine pas (par exemple « -21, 22,22,2 "," 33-2 "). Savez-vous si une telle bibliothèque existe? Je ne veux pas vraiment l'écrire moi-même car c'est un problème si évident que je suis sûr que je vais réinventer la roue.

Merci,

Nick

+0

Pourquoi exactement voulez-vous pas utiliser l'analyse de BigDecimal? C'est la manière la plus simple, vraiment. – Jorn

+0

Je voudrais savoir pourquoi vous ne voulez pas utiliser l'extrait que vous avez donné? Si vous avez besoin d'utiliser le numéro, vous devez l'analyser? C'est juste pour valider qu'une chaîne peut aller au backend tel quel? –

+0

Parce que les exceptions ne sont pas valables pour ce cas. Les exceptions sont, bien, pour les exceptions pas pour le contrôle du programme. – Malax

Répondre

6

I éviterait de réinventer cette méthode et aller avec Apache Commons. Si vous utilisez Spring, Struts ou bien d'autres bibliothèques java couramment utilisées, elles ont souvent des communs Apache inclus. Vous voulez le fichier commons-lang.jar. Voici la méthode NumberUtils vous voulez:

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

utiliser un regexp

+0

exactement. et ici http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html#BigDecimal(java.lang.String) vous avez de la nourriture pour vos tests unitaires. – flybywire

+0

+1 puisque Commons-Lang n'offre pas cela – skaffman

+0

Merci de m'avoir indiqué à commons-lang. trucs soignés! – Malax

2

Ouais une expression régulière devrait faire l'affaire. Je ne connais que le regexp .Net mais tous les langages regex sont assez similaires donc cela devrait vous aider à démarrer. Je ne l'ai pas testé, donc vous pourriez vouloir le faire un peu avec la classe Java regex.

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

Une partie de la syntaxe de commande Regex:
? - Élément facultatif
| - Opérateur OR. Fondamentalement, j'ai autorisé les nombres avec ou sans virgule s'ils étaient correctement formatés.
[] - Jeu de caractères autorisés
{,} - Maximum minimum de l'élément
* - Un nombre quelconque d'éléments, 0 à l'infini
+ - Au moins un élément, 1 à l'infini
\ - Caractère d'échappement
. - Tout caractère (Dès lors, pourquoi il a été échappé)

+0

+1 pour l'implémentation réelle – dfa

+0

Actuellement, cette expression correspond à 22,22,2.14123415e1 – Salandur

+0

Et elle ne correspondra pas à 1e-1. – Bombe

2

Voici une amende de travail fonction utilitaire regexp (ne pouvait pas s'adapter à la « » vérifier dans l'expression rationnelle tout en gardant lisible):

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'expression régulière exacte est spécifiée dans le Javadocs pour Double.valueOf(String).

Pour éviter d'appeler cette méthode sur une chaîne non valide et ayant un NumberFormatException être jeté, l'expression régulière ci-dessous peut être utilisée pour sélectionner la chaîne d'entrée:

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 
} 
Questions connexes