Библиотека Java для проверки, содержит ли строка число * без * исключений - PullRequest
8 голосов
/ 22 июля 2009

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

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"). Вы знаете, существует ли такая библиотека? Я не хочу писать это сам, так как это такая очевидная проблема, что я уверен, что заново изобрету колесо.

Спасибо

Ник

Ответы [ 5 ]

6 голосов
/ 22 июля 2009

Я бы не стал заново изобретать этот метод и пошел бы с 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 голосов
/ 22 июля 2009

Точное регулярное выражение указано в 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
}
3 голосов
/ 22 июля 2009
2 голосов
/ 22 июля 2009

Вот функция утилиты, основанная на регулярном выражении, работающая нормально (не может соответствовать проверке "" в регулярном выражении, сохраняя ее читабельной):

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 голосов
/ 22 июля 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...