2009-07-22 5 views
8

Я ищу метод, который возвращает логическое значение, если строка, переданная ею, является допустимым числом (например, «123.55e-9», «-333,556» «). Я не хотите просто сделать:Библиотека Java для проверки того, содержит ли строка число * без * исключений

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

Очевидно, что функция должна использовать государственную машину (DFA) для разбора строки, чтобы убедиться, что недопустимые примеры не обмануть его (например, «-21, 22.22.2 "," 33-2 "). Вы знаете, существует ли такая библиотека? Я действительно не хочу писать это сам, поскольку это такая очевидная проблема, что я уверен, что я буду изобретать колесо.

Спасибо,

Ник

+0

Почему именно вы не хотите использовать синтаксический анализ из BigDecimal? На самом деле это самый простой способ. – Jorn

+0

Хотелось бы узнать, почему вы не хотите использовать фрагмент, который вы дали? Если вам нужно _use_ номер, который вы должны проанализировать? Это просто проверка того, что строка может перейти на бэкэнд как есть? –

+0

Потому что Исключения не относятся к этому случаю. Исключения есть, ну, для исключений, а не для управления программой. – Malax

ответ

6

I не позволит повторно изобретать этот метод и пойти с Apache Commons. Если вы используете Spring, Struts или многие другие широко используемые java-библиотеки, они часто включают в себя Apache. Вам понадобится файл commons-lang.jar. Вот метод в NumberUtils вы хотите:

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

использовать regexp

+0

точно. и здесь http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html#BigDecimal(java.lang.String) у вас есть еда для ваших модульных тестов. – flybywire

+0

+1, так как Commons-Lang не предлагает этого – skaffman

+0

Спасибо, что указал мне на commons-lang. аккуратный материал! – Malax

2

Да регулярное выражение должно сделать трюк. Я знаю только .Net regexp, но все языки регулярных выражений довольно похожи, поэтому вы должны начать. Я не тестировал его, поэтому вы можете немного поиграть с классом Java regex.

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

Некоторые из Regex синтаксиса управления:
? - Дополнительный элемент
| Оператор ИЛИ. В основном я разрешал номера с запятыми или без них, если они были отформатированы правильно.
[] - Набор разрешенных символов
{,} - Минимальный максимум элемента
* - любое количество элементов, от 0 до бесконечности
+ - По крайней мере один элемент, от 1 до бесконечности
\ - побег характера
. - Любой символ (Следовательно, почему он сбежал)

+0

+1 для фактической реализации – dfa

+0

actualy это выражение будет соответствовать 22,22,2.14123415e1 – Salandur

+0

И оно не будет соответствовать 1e-1. – Bombe

2

Вот регулярное выражение на основе функции полезности работает отлично (не поместилась «» проверить в регулярном выражении при сохранении его доступным для чтения):

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

Точное регулярное выражение задается в Javadocs для Double.valueOf(String).

Чтобы избежать вызова этого метода на недопустимой строке и имеющей NumberFormatException быть выброшена, регулярное выражение ниже может быть использована для скрининга строки ввода:

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 
}