web-dev-qa-db-fra.com

Comment vérifier qu'une chaîne est analysable en double?

Existe-t-il un moyen natif (de préférence sans implémenter votre propre méthode) de vérifier qu'une chaîne est analysable avec Double.parseDouble()?

65
Louis Rhys

L'approche habituelle serait de le vérifier avec une expression régulière, comme cela est également suggéré dans la documentation Double.valueOf(String) .

L'expression rationnelle fournie ici (ou incluse ci-dessous) devrait couvrir tous les cas de virgule flottante valides. Vous n'avez donc pas besoin de la manipuler, vous risquez de manquer certains points plus fins.

Si vous ne voulez pas faire ça, try catch est toujours une option.

Le regexp suggéré par le JavaDoc est inclus ci-dessous:

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
}
44
Johannes Wachter

Comme d'habitude, Apache a une bonne réponse de Apache Commons-Lang sous la forme de org.Apache.commons.lang3.math.NumberUtils.isNumber(String)

Gère les nulls, pas de bloc try/catch requis.

54
bluedevil2k

Vous pouvez toujours envelopper Double.parseDouble () dans un bloc catch catch.

try
{
  Double.parseDouble(number);
}
catch(NumberFormatException e)
{
  //not a double
}
51
jdc0589

Quelque chose comme ci-dessous devrait suffire: -

String decimalPattern = "([0-9]*)\\.([0-9]*)";  
String number="20.00";  
boolean match = Pattern.matches(decimalPattern, number);
System.out.println(match); //if true then decimal else not  
9
CoolBeans

La bibliothèque Google de goyaves fournit une méthode d'assistance Nice pour le faire: Doubles.tryParse(String) . Vous l'utilisez comme Double.parseDouble mais il retourne null plutôt que de lancer une exception si la chaîne ne s’analyse pas en double.

8
ruhong

Toutes les réponses sont OK, selon votre niveau académique. Si vous souhaitez suivre les spécifications de Java avec précision, utilisez les éléments suivants:

private static final Pattern DOUBLE_PATTERN = Pattern.compile(
    "[\\x00-\\x20]*[+-]?(NaN|Infinity|((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)" +
    "([eE][+-]?(\\p{Digit}+))?)|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)|" +
    "(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))" +
    "[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*");

public static boolean isFloat(String s)
{
    return DOUBLE_PATTERN.matcher(s).matches();
}

Ce code est basé sur les JavaDocs sur Double .

7
Zach-M