- Как определить, является ли строка числом?
- 9 ответов 9
- Как проверить, является ли строка числовой в Java
- 30 ответов
- Как проверить, содержит ли строка только цифры в Java
- Вопрос 1:
- Вопрос 2:
- Вопрос 3
- Не быстрее ли скомпилировать шаблон регулярных выражений?
- Проверить, является ли строка числовой в Java
- 1. Вступление
- 2. Предпосылкой
- 3. Использование простой Java
- 3.1. Проверка входов с помощью Scanner
- 4. Использование регулярных выражений
- 5. Использование Apache Commons
- 5.1. NumberUtils.isCreatable (String)
- 5.2. NumberUtils.isParsable (String)
- 5.3. _StringUtils.isNumeric (CharSequence ) ___
- 5.4. StringUtils.isNumericSpace (CharSequence)
- 6. Ориентиры
- 7. Заключение
- Как проверить, является ли строка числовой в Java
- 39 ответов
Как определить, является ли строка числом?
Я делал так, но мне кажется такой подход в чем-то неправильным:
9 ответов 9
Я так понимаю, цель именно на Integer проверить? Тогда можно:
такое регулярное подойдёт.
Метод, описанный в вопросе, и есть самый правильный метод.
Методы, которые проверяют, состоит ли строка лишь из цифр, не справятся с переполнением (попробуйте число 100000000000000000000000000000000 ). Правильный паттерн для целого числа такой:
и поверьте, вам не хочется отлаживать его или адаптировать для других типов.
При этом решения, основанные на паттернах, не будут учитывать локаль и разрешённые разделители разрядов. Так что попробовать распарсить и поймать исключение — практически единственно правильное решение.
Есть очень хороший static-метод в commons-lang (класс NumberUtils ), который учитывает множество особенностей чисел Java:
В связи с повышенным интересом по данному вопросу, сделал маленькое исследование 🙂
В исследовании принимали участия классы:
(@VladD, извиняюсь, понимаю, что делает ваш регэксп, но завести его у меня не получилось)
Вывода много, поэтому вкратце:
Start performance test for core.impl.CharacterDelegator Ints: 125ms Numbers: 67ms Numbers with 25% errors: 50ms Small Ints: 43ms
Start performance test for core.impl.ComplexMatcher Ints: 10825ms Numbers: 11134ms Numbers with 25% errors: 10606ms Small Ints: 10380ms
Start performance test for core.impl.InnerSetImpl Ints: 50ms Numbers: 52ms Numbers with 25% errors: 54ms Small Ints: 42ms
Start performance test for core.impl.NumberUtilsDelegator Ints: 111ms Numbers: 91ms Numbers with 25% errors: 99ms Small Ints: 51ms
Start performance test for core.impl.SimpleMatcher Ints: 1072ms Numbers: 853ms Numbers with 25% errors: 847ms Small Ints: 766ms
Start performance test for core.impl.GuavaDelegator Ints: 131ms Numbers: 108ms Numbers with 25% errors: 124ms Small Ints: 119ms
Start performance test for core.impl.SimpleMatcherWithDot Ints: 3069ms Numbers: 5855ms Numbers with 25% errors: 5484ms Small Ints: 2548ms
Start performance test for core.impl.SimpleParser Ints: 157ms Numbers: 2189ms Numbers with 25% errors: 2117ms Small Ints: 81ms
Start performance test for core.impl.GuavaComplexDelegator Ints: 980ms Numbers: 943ms Numbers with 25% errors: 1016ms Small Ints: 837ms
Тест построен следующим образом
Генерируем 2 рандомных списка со стрингами (числа). Тут есть 4 варианта:
Делаем тестовый прогон на 10_000 элементах.
Из приведенных выкладок видно, что NumberUtils работает быстрее всего. Схожее время работы у простого варианты Guava`ы и простых regexp. Даже добавление простой точки значительно замедляет код. Также замечу, что код @Sergey работает очень быстро, но он рассчитан на проверку строго интов.
А если вдруг у вас стоит специфическая задача на парсинг не просто чисел, но чисел в Java-нотациях, то это единственный полностью рабочий вариант.
(Все вышесказанное относится только к приведенному коду. Я не исключаю, что можно придумать (или даже существует) более правильное или более быстрое решение).
Как проверить, является ли строка числовой в Java
Как бы вы проверили, была ли строка числом перед ее разбором?
30 ответов
вы также можете использовать StringUtils.isNumericSpace возвращает true для пустых строк и игнорирует внутренние пробелы в строке. (Связанной документации содержит подробные примеры для каждого метода.)
это обычно делается с помощью простой определяемой пользователем функции (т. е. свернуть свою собственную «числовую» функцию).
однако, если вы вызываете эту функцию много, и вы ожидаете, что многие из проверок потерпят неудачу из-за того, что не являются числом, производительность этого механизма не будет большой, так как вы полагаетесь на исключения, создаваемые для каждого сбоя, что является довольно дорогостоящей операцией.
альтернативным подходом может быть чтобы использовать регулярное выражение для проверки правильности числа:
будьте осторожны с вышеупомянутым механизмом регулярного выражения, хотя, поскольку он потерпит неудачу, если вы используете неарабские цифры (т. е. цифры, отличные от 0 до 9). Это связано с тем, что часть» \d » регулярного выражения будет соответствовать только 7 и фактически не является международной числовой информацией. (Спасибо OregonGhost за указание на это!)
или даже другой альтернативой является использование встроенного Java Ява.текст.Numberformat объект, чтобы увидеть, если после синтаксического анализа строки позиция синтаксического анализатора находится в конце строки. Если это так, мы можем предположить, что вся строка является числовым:
Если вы находитесь на Android, то вы должны использовать:
сохранить его простым. в основном каждый может «перепрограммировать» (то же самое).
UPDATE: как указал Жан-Франсуа Корбетт в комментарии, приведенный выше код будет проверять только положительные целые числа, которые охватывают большую часть моего варианта использования. Ниже приведен обновленный код, который правильно проверяет десятичные числа в соответствии с локалем по умолчанию, используемым в вашей системе, с предположением, что десятичный разделитель встречается только один раз в строке.
Java 8 лямбда-выражения.
не используйте исключения для проверки значений. Используйте util libs вместо apache NumberUtils:
редактировать:
обратите внимание, что если ваша строка начинается с 0, NumberUtils будет интерпретировать ваше значение как шестнадцатеричное.
почему все настаивают на решениях исключений / регулярных выражений?
хотя я могу понять, что большинство людей в порядке с использованием try / catch, если вы хотите делать это часто. это может быть чрезвычайно утомительно.
то, что я сделал здесь, это взять регулярное выражение, методы parseNumber() и метод поиска массива, чтобы увидеть, который был наиболее эффективным. На этот раз я смотрел только на целые числа.
результаты в скорости я получил были:
отказ от ответственности: я не утверждаю, что эти методы 100% оптимизированы, они просто для демонстрации данных
исключения выиграли, если и только если число 4 символа или меньше, и каждая строка всегда ряд. в таком случае зачем вообще чек?
короче говоря, это очень больно, если вы часто сталкиваетесь с недопустимыми числами с помощью try/catch, что имеет смысл. Важное правило я всегда следовать никогда не используйте try / catch для потока программы. Вот пример почему.
интересно, что простой, если char 9 был чрезвычайно прост в написании, легко запоминается (и должен работать на нескольких языках) и выигрывает почти все тестовые сценарии.
единственным недостатком является то, что я предполагаю целое число.parseInt () может обрабатывать номера, отличные от ASCII, в то время как метод поиска массива-нет.
для тех, кто интересуется, почему я сказал, что это легко помните, что массив символов один, если вы знаете, что нет отрицательных знаков, вы можете легко уйти с чем-то конденсированным, как это:
наконец, в качестве заключительного замечания мне было интересно узнать об операторе назначения в принятом примере со всеми голосами. Добавление в задание
не только бесполезно, так как вы даже не используете значение, но он тратит время обработки и увеличивает время выполнения на несколько наносекунд (что привело к 100-200 МС увеличение в тестах). Я не понимаю, зачем кому-то это делать, так как на самом деле это дополнительная работа для снижения производительности.
вы думаете, что это будет оптимизировано. хотя, возможно, я должен проверить байт-код и посмотреть, что делает компилятор. Это не объясняет, почему он всегда показывался мне более длинным, хотя если он каким-то образом оптимизирован. поэтому мне интересно, что происходит. Как Примечание: под lengthier я имею в виду запуск теста для 10000000 итераций и запуск этой программы несколько раз (10x+) всегда показывали, что он медленнее.
EDIT: обновлен тест для символа.isDigit()
также он будет отклонять любое число с ведущим’+’
альтернативой, которая позволяет избежать этих двух незначительных проблем, является
Как проверить, содержит ли строка только цифры в Java
В Java для класса String существует метод, называемый match, как использовать этот метод, чтобы проверить, имеет ли моя строка только цифры с регулярным выражением. Я пробовал с примерами ниже, но оба они вернули мне ложные результаты.
Согласно регулярным выражениям Java, + означает “один или несколько раз”, а \d означает “цифра”.
Примечание. “Двойная обратная косая черта” является escape-последовательностью для получения одной обратной косой черты, поэтому \\d в строке Java дает фактический результат: \d
Ссылки:
Изменить: из-за некоторой путаницы в других ответах я пишу тестовый пример и подробно объясню некоторые вещи.
Во-первых, если вы сомневаетесь в правильности этого решения (или других), запустите этот тестовый пример:
Вопрос 1:
Нет. В java метод matches (который был указан в вопросе) соответствует полной строке, а не фрагментам. Другими словами, нет необходимости использовать ^\\d+$ (хотя это также правильно). Пожалуйста, посмотрите последний негативный тестовый пример.
Вопрос 2:
Нет. Регулярное выражение \\d* будет соответствовать пустой строке, но \\d+ – нет. Звезда * означает ноль или более, тогда как плюс + означает один или более. Пожалуйста, посмотрите первый отрицательный тестовый пример.
Вопрос 3
Не быстрее ли скомпилировать шаблон регулярных выражений?
Вы также можете использовать NumberUtil.isNumber(String str) из Apache Commons
Еще одно решение, которое еще не было опубликовано:
и исключение catch, оно обрабатывает знак минус.
Несмотря на то, что количество цифр ограничено, это фактически создает переменную данных, которые могут быть использованы, что, я думаю, является наиболее распространенным вариантом использования.
Вы должны разрешить больше цифры (знак + ), как в:
Использование регулярных выражений является дорогостоящим с точки зрения производительности. Попытка разобрать строку как длинное значение неэффективна и ненадежна, и может быть не то, что вам нужно.
Я предлагаю просто проверить, является ли каждый символ цифрой, что можно эффективно выполнить с помощью ямбда-выражений Java 8:
В соответствии с Oracle Java Documentation:
шаблон 8 означает цифру. То же, что и ‘\ d’.
“+” означает, что он появляется больше раз.
” для integer или float.
Проверить, является ли строка числовой в Java
1. Вступление
Часто при работе с _Strings нам нужно выяснить, является ли String _ допустимым числом или нет.
После того, как мы закончили обсуждение различных реализаций, мы будем использовать тесты, чтобы понять, какие методы являются оптимальными.
Давайте начнем с некоторых предварительных условий, прежде чем перейти к основному содержанию.
2. Предпосылкой
В последней части этой статьи мы будем использовать внешнюю библиотеку Apache Commons. Чтобы включить эту зависимость, добавьте следующие строки в pom.xml :
3. Использование простой Java
, new BigInteger (String)
Давайте посмотрим на этот метод в действии:
Эти методы также обсуждаются в ссылке:/java-string-conversions[Java String Conversions].
3.1. Проверка входов с помощью Scanner
Например, следующие API проверяют, имеет ли ввод тип integer, long или float :
scanner.hasNextInt ()
scanner.hasNextLong ()
scanner.hasNextFloat ()
Эти API возвращают простые true или false в зависимости от типов ввода. Мы можем использовать эти API, чтобы убедиться, что следующий ввод имеет желаемый тип.
Следующий фрагмент проверяет, является ли ввод целым числом или нет:
Точно так же мы можем использовать другие API для проверки других типов.
4. Использование регулярных выражений
Но само собой разумеется, что мы можем определенно изменить это регулярное выражение, чтобы определить и справиться с широким спектром правил. Здесь мы сделаем это просто.
Давайте разберем это регулярное выражение и посмотрим, как оно работает:
мы ищем одну или несколько цифр, за которыми следует точка. Знак вопроса, в конце концов, означает, что эта полная группа является необязательной.
А пока давайте создадим метод, используя приведенное выше регулярное выражение:
Давайте теперь посмотрим на некоторые утверждения для вышеуказанного метода:
5. Использование Apache Commons
В этом разделе мы обсудим различные методы, доступные в библиотеке Apache Commons.
5.1. NumberUtils.isCreatable (String)
Этот метод принимает:
, Шестнадцатеричные числа, начинающиеся с 0x или 0X
, Восьмеричные числа, начинающиеся с 0
, Научная нотация (например, 1.05e-10)
, Числа, помеченные квалификатором типа (например, 1L или 2.2d)
Если предоставленная строка _null или empty/blank , то она не считается числом, и этот метод вернет false _ в этом случае
Давайте запустим несколько тестов, используя этот метод:
Обратите внимание, как мы получаем _true _ утверждения для шестнадцатеричных чисел, восьмеричных чисел и научных обозначений в строках 6, 7 и 8 соответственно.
Также в строке 14 строка _ «09» turns false because предыдущего «0» указывает, что это восьмеричное число, а «09» _ не является действительным восьмеричным числом.
5.2. NumberUtils.isParsable (String)
Метод _https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html#isParsable-java.lang.String-[NumberUtils.isParsable (String)] проверяет, является ли данная String _ анализируемой или нет.
Давайте посмотрим на некоторые утверждения:
Мы можем использовать этот метод в качестве замены того, что мы делали в разделе 3, где мы пытаемся проанализировать число и проверить наличие ошибки.
5.3. _StringUtils.isNumeric (CharSequence ) ___
Метод _https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isNumeric-java.lang.CharSequence-[StringUtils.isNumeric (CharSequence)] _ строго проверяет для цифр Юникода. Это означает:
, Любые цифры с любого языка, которые являются цифрами Unicode, являются приемлемыми
, Так как десятичная точка не считается цифрой Unicode, это не
Давайте теперь посмотрим на этот метод в действии:
Обратите внимание, что входные параметры в строках 2 и 3 представляют числа __123 на арабском и деванагари соответственно. Так как они являются действительными цифрами Unicode, этот метод возвращает true __onon.
5.4. StringUtils.isNumericSpace (CharSequence)
6. Ориентиры
Прежде чем мы завершим эту статью, давайте кратко рассмотрим результаты тестов, которые помогут нам проанализировать, какие из перечисленных методов являются оптимальными:
Как мы видим, наиболее дорогостоящая операция с регулярными выражениями, за которой следует базовое решение на основе Java. Все остальные операции, использующие библиотеку Apache Commons, в целом одинаковы.
7. Заключение
Как проверить, является ли строка числовой в Java
Как бы вы проверили, был ли String числом, прежде чем его анализировать?
39 ответов
Вы также можете использовать StringUtils.isNumericSpace который возвращается true для пустых строк и игнорирует внутренние пробелы в строке. (Связанные javadocs содержат подробные примеры для каждого метода.)
Как правило, это делается с помощью простой пользовательской функции (например, «isNumeric»).
Однако, если вы часто вызываете эту функцию и ожидаете, что многие проверки не пройдут из-за того, что они не являются числом, производительность этого механизма будет невелика, так как вы полагаетесь на исключения, создаваемые для каждой ошибки, что довольно дорогая операция.
Альтернативный подход может заключаться в использовании регулярного выражения для проверки действительности числа:
Будьте осторожны с вышеупомянутым механизмом RegEx, так как он потерпит неудачу, если вы используете неарабские цифры (то есть цифры, отличные от 0 до 9). Это связано с тем, что часть «\d» в RegEx будет совпадать только с 1 и фактически не будет численно известна на международном уровне. (Спасибо OregonGhost за указание на это!)
Или даже другой альтернативой является использование встроенного в Java объекта java.text.NumberFormat, чтобы проверить, находится ли после синтаксического анализа строки позиция парсера в конце строки. Если это так, мы можем предположить, что вся строка числовая:
Если вы на Android, то вы должны использовать:
будь проще в основном каждый может «перепрограммировать» (тоже самое).
Java 8 лямбда-выражений.
ОБНОВЛЕНИЕ: Как указал Жан-Франсуа Корбетт в комментарии, приведенный выше код будет проверять только положительные целые числа, что покрывает большую часть моего варианта использования. Ниже приведен обновленный код, который корректно проверяет десятичные числа в соответствии с локалью по умолчанию, используемой в вашей системе, при условии, что десятичный разделитель встречается в строке только один раз.
Не используйте исключения для проверки ваших значений. Вместо этого используйте Util libs, как apache NumberUtils:
Редактировать:
Обратите внимание, что если ваша строка начинается с 0, NumberUtils будет интерпретировать ваше значение как шестнадцатеричное.
Почему все стремятся к решениям исключений / регулярных выражений?
Хотя я понимаю, что большинству людей хорошо использовать try / catch, но если вы хотите делать это часто. это может быть очень сложным.
Здесь я использовал регулярное выражение, методы parseNumber() и метод поиска в массиве, чтобы увидеть, какой из них наиболее эффективен. На этот раз я посмотрел только на целые числа.
Результаты в скорости я получил:
Отказ от ответственности: я не утверждаю, что эти методы оптимизированы на 100%, они просто для демонстрации данных
Исключения выигрывают тогда и только тогда, когда число составляет 4 символа или менее, а каждая строка всегда является числом. в таком случае, зачем вообще чек?
Короче говоря, это очень больно, если вы часто сталкиваетесь с недопустимыми числами с помощью try / catch, что имеет смысл. Важное правило, которому я всегда следую, НИКОГДА не используйте try / catch для выполнения программы. Это пример почему.
Интересно, что простой if char 9 было чрезвычайно просто написать, легко запомнить (и должно работать на нескольких языках) и выигрывает почти во всех тестовых сценариях.
Единственным недостатком является то, что я предполагаю, что Integer.parseInt() может обрабатывать числа не ASCII, в то время как метод поиска в массиве не делает.
Для тех, кто задается вопросом, почему я сказал, что легко запомнить массив символов один, если вы знаете, что нет отрицательных признаков, вы можете легко сойтись с чем-то сжатым, как это:
И, наконец, в качестве заключительного замечания, мне было любопытно, что оператор присваивания в принятом примере набрал все голоса. Добавление в назначение
не только бесполезен, так как вы даже не используете это значение, но и тратит время обработки и увеличивает время выполнения на несколько наносекунд (что привело к увеличению тестов на 100-200 мс). Я не понимаю, почему кто-то так поступил, потому что это дополнительная работа по снижению производительности.
Вы могли бы подумать, что это будет оптимизировано. хотя, возможно, мне следует проверить байт-код и посмотреть, что делает компилятор. Это не объясняет, почему он всегда показывался мне более длинным, хотя, если он каким-то образом оптимизирован. поэтому мне интересно, что происходит. Как примечание: под продолжительностью я имею в виду запуск теста для 10000000 итераций, и запуск этой программы несколько раз (10x+) всегда показывал, что он медленнее.









