Подтвердить что ты не робот

Как узнать, является ли значение, содержащееся в строке, двойным или нет

В Java я пытаюсь выяснить, является ли значение, содержащееся в строке, двойным или нет?

4b9b3361

Ответ 1

    boolean isDouble(String str) {
        try {
            Double.parseDouble(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

Ответ 2

В для Double есть примечание:

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

Окончательный вид следующих регулярных выражений довольно длинный:

[\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]*

Используя этот метод, вы можете легко исключить некоторые специальные удвоения, такие как Infinity и NaN, которые оба признаны Double.parseDouble. Например, например:

String regExp = "[\\x00-\\x20]*[+-]?(((((\\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]*";
boolean matches = yourString.matches(regExp);

Ответ 3

Вы можете создать Scanner(String) и использовать hasNextDouble(). Из своего javadoc:

Возвращает true, если следующий токен в этом входе сканера может быть интерпретируется как двойное значение, используя метод nextDouble(). Сканер не продвигается мимо каких-либо входных данных.

Например, этот фрагмент:

List<String> values = Arrays.asList("foo", "1", "2.3", "1f", "0.2d", "3.14");
for (String source : values) {
    Scanner scanner = new Scanner(source);
    System.out.println(String.format("%4s: %s", source, scanner.hasNextDouble()));
}

Произведет следующий вывод:

 foo: false
   1: true
 2.3: true
  1f: false
0.2d: false
3.14: true

Ответ 4

Использование Scanner будет значительно медленнее, чем при использовании Double.parseDouble(String s).

private static Random rand = new Random();
private static final String regExp = "[\\x00-\\x20]*[+-]?(((((\\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]*";
private static final Pattern pattern = Pattern.compile(regExp);

public static void main(String[] args) {

    int trials = 50000;
    String[] values = new String[trials];

    // initialize the array
    // about half the values will be parsable as double
    for( int i = 0; i < trials; ++i ) {
        double d = rand.nextDouble();
        boolean b = rand.nextBoolean();

        values[i] = (b ? "" : "abc") + d;
    }

    long start = System.currentTimeMillis();

    int parseCount = 0;
    for( int i = 0; i < trials; ++i ) {
        if( isDoubleParse(values[i]) ) {
            parseCount++;
        }
    }

    long end = System.currentTimeMillis();
    long elapsed = end - start;

    System.out.println("Elapsed time parsing: " + elapsed + " ms");
    System.out.println("Doubles: " + parseCount);

    // reset the timer for the next run
    start = System.currentTimeMillis();

    int scanCount = 0;
    for( int i = 0; i < trials; ++i ) {
        if( isDoubleScan(values[i]) ) {
            scanCount++;
        }
    }

    end = System.currentTimeMillis();
    elapsed = end - start;

    System.out.println("Elapsed time scanning: " + elapsed + " ms");
    System.out.println("Doubles: " + scanCount);


    // reset the timer for the next run
    start = System.currentTimeMillis();

    int regexCount = 0;
    for( int i = 0; i < trials; ++i ) {
        if( isDoubleRegex(values[i]) ) {
            regexCount++;
        }
    }

    end = System.currentTimeMillis();
    elapsed = end - start;

    System.out.println("Elapsed time regex (naive): " + elapsed + " ms");
    System.out.println("Doubles: " + naiveRegexCount);


    // reset the timer for the next run
    start = System.currentTimeMillis();

    int compiledRegexCount = 0;
    for( int i = 0; i < trials; ++i ) {
        if( isDoubleCompiledRegex(values[i]) ) {
            compiledRegexCount++;
        }
    }

    end = System.currentTimeMillis();
    elapsed = end - start;

    System.out.println("Elapsed time regex (compiled): " + elapsed + " ms");
    System.out.println("Doubles: " + compiledRegexCount);
}


public static boolean isDoubleParse(String s) {
    if( s == null ) return false;
    try {
        Double.parseDouble(s);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

public static boolean isDoubleScan(String s) {
    Scanner scanner = new Scanner(s);
    return scanner.hasNextDouble();
}

public static boolean isDoubleRegex(String s) {
    return s.matches(regExp);
}

public static boolean isDoubleCompiledRegex(String s) {
    Matcher m = pattern.matcher(s);
    return m.matches();
}

Когда я запускаю код выше, я получаю следующий вывод:

Истекшее время разбора: 235 мс
Парные разряды: 24966
Истекшее время сканирования: 31358 мс
Парные разряды: 24966
Истекшее время регулярного выражения (наивное): 1829 ms
Парные разряды: 24966
Игре прошедшего времени (скомпилировано): 109 мс
Парный разряд: 24966

Метод регулярного выражения выполняется довольно быстро, учитывая сложность регулярного выражения, но все же не так быстро, как просто синтаксический анализ с использованием Double.parseDouble(s). Как отмечено в комментариях, есть несколько значений, таких как NaN, которые проходят через парсер, который, вероятно, не должен.

Обновление:

Предварительная компиляция регулярного выражения, предложенная @Gabe, имеет большое значение. Скомпилированный регулярный метод теперь является явным победителем.

Ответ 5

public boolean isDouble(String value) {
    try {
        Double.parseDouble(value);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

Ответ 6

Вы можете использовать класс util из Apache Commons Lang:

NumberUtils.isNumber(aString);

Он недействителен и не требует использования блока try-catch.

Примечание: для парсинга двойников он работает, если десятичный разделитель является точкой .

Изменить: isNumber устарел и будет удален из Lang 4.0

Лучше использовать:

NumberUtils.isCreatable(aString);

Ответ 7

Вы можете попытаться проанализировать его с помощью Double.parseDouble(String s)

Это приведет к возврату double, если синтаксический анализ был успешным и исключение, если оно не обрабатывается.

Итак, вы можете обернуть все это в функцию, содержащую try-catch, и вернуть false, если у вас есть исключение или true, если вы получили фактическое значение.

Ответ 8

Я бы предложил следующее:

try {
  d = Double.parseDouble(myString);
}
catch (NumberFormatException ex) {
    // Do something smart here...
}

Ответ 10

Другие предположили, что вы также можете знать, что вход НЕ выражен как целое. В зависимости от ваших требований это может сделать работу быстрой и грязной:

public static void main(String[] args) throws Exception {
    System.out.println(isNonIntegerDouble("12"));  //false
    System.out.println(isNonIntegerDouble("12.1")); //true
    System.out.println(isNonIntegerDouble("12.0")); //true
}

public static boolean isNonIntegerDouble(String in) {
    try {
        Double.parseDouble(in);
    } catch (NumberFormatException nfe) {
        return false;
    }
    try {
        new BigInteger(in);
    } catch (NumberFormatException nfe) {
        return true;
    }
    return false;
}

В этот момент я считаю, что сопоставление строк было бы более подходящим выбором.

Ответ 11

В строке можно использовать следующее регулярное выражение:

[-+]?[0-9]*\.?[0-9]*

и посмотрите, совпадает ли он.

Ответ 12

Я изменил метод Jonas 'isInteger(), чтобы придумать метод isDecimal() для моего собственного проекта, и я перечисляю приведенные ниже коды.

Может быть, кто-то может изменить, добавьте больше кодов, чтобы различать double и float.

Он должен выглядеть довольно быстро и, вероятно, лучше, чем регулярное выражение, хотя я не проверял. Единственный недостаток - это неправильная работа в случае переполнения и т.д.

Обратите внимание, что я ссылаюсь на сообщение Билла в Каков наилучший способ проверить, является ли String целочисленным в Java?

    public boolean isDecimal(String str) {
        if (str == null) {
            return false;
        }
        int length = str.length();
        if (length == 1 ) {
            return false;
        }
        int i = 0;
        if (str.charAt(0) == '-') {
            if (length < 3) {
                return false;
            }
            i = 1;
        }
        int numOfDot = 0;
        for (; i < length; i++) {
            char c = str.charAt(i);
            if (c == '.')
                numOfDot++;
            else if (c == '/')
                return false;
            else if (c < '.' || c > '9') {
                return false;
            }
        }
        if (numOfDot != 1 )
            return false;

        return true;
    }

Ответ 13

Если бы вы могли найти способ выделения числа из строки, возможно, используя метод split. И скажем num[1] = 25;, тогда вы можете сделать что-то подобное, чтобы проверить, есть ли у него двойной.

boolean isDouble;
if(num[1].contains(".")){
isDouble = true;
}
else{
isDouble = false;
}

Ответ 14

  Мы должны обработать NumberFormatException и исключение нулевого указателя, чтобы проверить, является ли данная строка числовой или буквенно-цифровой

public static boolean isNumeric(String strNum) {
        try {
           Double.parseDouble(strNum);
        } catch (NumberFormatException | NullPointerException nfe) {
            return false;
        }
        return true;
    }

Ответ 15

private boolean checkIsNumber(Object value) {
try {
    boolean isNumber = NumberUtils.isNumber((String) value);
    if (!isNumber) {
        Double.parseDouble((String) value);
    }
} catch (Exception e) {
    return false;
}
return true;

}

Ответ 16

Try:

boolean isDouble;
try
{
   Double.parseDouble("1.2");
   isDouble = true;
}catch(Exception e){
   isDouble = false;
}

Хотя обычно не рекомендуется использовать исключения, такие как условные обозначения.

Ответ 17

    public boolean isDouble( String input )  
    {  
       try  
       {  
          Double.parseDouble( input );  
          return true;  
       }  
       catch( Exception e)  
       {  
         return false;  
      }  
  }