8
votes

Bibliothèque Java pour vérifier si une chaîne contient un numéro * sans * exceptions

Je recherche une méthode qui renvoie un booléen si la chaîne qu'il est transmise est un nombre valide (par exemple. 123.55E-9 "," -333 556 "). Je ne veux pas veux juste faire: xxx

clairement, la fonction doit utiliser une machine à états (DFA) pour analyser la chaîne pour assurer des exemples non valides t-il tromper (par exemple "-21,22,222,22", "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 aussi évident que je suis sûr que je voudrais réinventer la roue.

Merci,

Nick


7 commentaires

Pourquoi exactement ne voulez-vous pas utiliser l'analyse de BigDecimal? C'est le moyen le plus simple, vraiment.


J'aimerais savoir pourquoi vous ne voulez pas utiliser l'extrait que vous avez donné? Si vous avez besoin de utiliser le numéro, vous devez l'analyser? Il suffit de valider qu'une chaîne peut aller au backend tel quel?


Parce que les exceptions ne sont pas destinées à cette affaire. Les exceptions sont, eh bien, pour des exceptions non pour le contrôle du programme.


J'ai rencontré cette question à quelques reprises à quelques reprises et, bien que cela se sent incorrect d'exploiter une exception de cette façon, il est toujours le moyen le plus simple de le faire. C'est simple, bien testé et fonctionne. Je ne cherche plus d'autres moyens.


Je suis d'accord avec ça en théorie. Si vous pouviez contrôler l'analyse utilisée dans BigDecimal, vous pouvez le modifier pour renvoyer une certaine valeur indiquant l'analyse de l'analyse, au lieu de lancer une exception. Cependant, étant donné que vous ne pouvez pas contrôler cela, je ne ferais pas ma propre mise en œuvre pour quelque chose qui existe déjà, simplement parce que la bigdecimale est "pas très gentille parce qu'elle utilise des exceptions".


-1 comme cela devient sérieusement difficile. BigDecimal le gère pour vous. Si vous n'aimez pas l'exception, mettez cela dans une classe d'utils quelque part et appelez-le »SafeSnum ()" ou d'autres. Apache Concnons a des contrôles de validation des chaînes qui feront également ce genre de chose.


Je ne voulais pas utiliser des exceptions telles qu'elles sont lentes - elles font un appel natif pour remplir la trace de la pile (FillinstackTrace () en loable). Je n'ai pas réalisé que Commons avait une méthode comme celle-ci ... c'est exactement ce que je cherchais.


5 Réponses :


3
votes

Utilisez un REGEXP


1 commentaires

exactement. et ici Java.sun.com/j2se/1.5.0/docs/aplia/java/math/... Vous avez des aliments pour vos tests d'unité.



2
votes

Ouais une expression régulière devrait faire l'affaire. Je connais seulement .Net Regexp mais toutes les langues de regex sont assez similaires, cela devrait vous permettre de commencer. Je n'ai pas testé cela pour que vous puissiez peut-être frapper un peu avec la classe Java Regex. XXX

Une partie de la syntaxe de contrôle de regex:
? - Élément optionnel
| - ou opérateur. Fondamentalement, j'ai autorisé des chiffres avec ou sans virgules s'ils étaient correctement formatés.
[] - Ensemble de caractères autorisés
{,} - maximum minimum d'élément
* - Tout nombre d'éléments, 0 à l'infini
+ - Au moins un élément, 1 à l'infini
\ - caractère d'échappement
. - N'importe quel caractère (donc pourquoi il a été échappé)


1 commentaires

En fait, cette expression correspondra au 22,22,2.14123415E1



2
votes

Voici une fonction utilitaire basée sur REGEXP fonctionnant bien (ne pouvait pas correspondre à la "" Vérification de la réégycle tout en le 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));
        }
    }

}


0 commentaires

6
votes

J'éviterais de réinventer cette méthode et d'aller avec Apache Commons. Si vous utilisez le ressort, les jambes de jambes ou de nombreuses autres bibliothèques Java couramment utilisées, elles ont souvent Apache Commons inclus. Vous voudrez le fichier Commons-Lang.jar. Voici la méthode dans Numberutils vous souhaiteriez:

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


0 commentaires

3
votes

L'expression régulière exacte est spécifiée dans les Javadocs pour double.valueof (chaîne) code> .

Pour éviter d'appeler cette méthode sur une chaîne non valide et ayant un NumberFormatxception code> être lancé, l'expression régulière ci-dessous peut être utilisée pour afficher la chaîne d'entrée: p>

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
}


0 commentaires