Вы также можете использовать, StringUtils.isNumericSpaceкоторый возвращает trueпустые строки и игнорирует внутренние пробелы в строке. Другой способ заключается в использовании, NumberUtils.isParsableкоторый в основном проверяет число, доступное для анализа в соответствии с Java. (Связанные javadocs содержат подробные примеры для каждого метода.)
StringUtils.isNumeric()вероятно, здесь не подходит, так как он проверяет, является ли строка последовательностью цифр. Было бы хорошо для большинства целых, но не для чисел с десятичными числами, разделителями групп и т. Д.
Джефф Меркадо
42
заново изобретать колесо, потому что вы не включаете целую библиотеку, потому что вам нужна трехстрочная функция в одном месте.
dalvarezmartinez1
12
Правда ли стоит добавить целую библиотеку для этой функции? Очевидно, что если он используется с другими вещами, это здорово, но это, вероятно, излишне, учитывая, что люди решили это в одной строке кода.
Вода
7
Не работает с негативами. И половина всех чисел отрицательна, так что .....
Пол Дрейпер
6
@PaulDraper: Вы правы, StringUtilsне поддерживает начальные знаки, но вы должны проверить NumberUtils.isCreatable, он правильно поддерживает негативы.
Palacsint
905
Как правило, это делается с помощью простой пользовательской функции (например, «isNumeric»).
Однако, если вы часто вызываете эту функцию и ожидаете, что многие проверки не пройдут из-за того, что они не являются числом, производительность этого механизма будет невелика, поскольку вы полагаетесь на исключения, создаваемые для каждой ошибки, что довольно дорогая операция.
Альтернативный подход может состоять в том, чтобы использовать регулярное выражение для проверки действительности числа:
publicstaticboolean isNumeric(String str){return str.matches("-?\\d+(\\.\\d+)?");//match a number with optional '-' and decimal.}
Будьте осторожны с вышеупомянутым механизмом RegEx, так как он потерпит неудачу, если вы используете неарабские цифры (то есть цифры, отличные от 0 до 9). Это связано с тем, что часть "\ d" в RegEx будет совпадать только с [0-9] и фактически не будет численно известна на международном уровне. (Спасибо OregonGhost за указание на это!)
Или даже другой альтернативой является использование встроенного в Java объекта java.text.NumberFormat, чтобы проверить, находится ли после синтаксического анализа строки позиция парсера в конце строки. Если это так, мы можем предположить, что вся строка числовая:
\ D в Java Regex соответствует только латинским цифрам? Если это похоже на регулярные выражения .NET, вы столкнетесь
OregonGhost
3
Решение numberFormatter, вероятно, лишь незначительно лучше, чем перехват номера NumberFormatException. Я подозреваю, что лучший способ - это использовать регулярные выражения.
Чии
11
Обратите внимание, что .в вашем регулярном выражении будет соответствовать любой символ, а не только символ десятичного разделителя.
jqno
9
+1 для реализации за счет попробовать / поймать. Это на самом деле ужасный подход для использования в долгосрочной перспективе для повторного использования, но на самом деле мы застряли с этим в Java.
Демонголем
5
Обратите внимание, что нет таких вещей, как «латинские цифры», а цифры 0-9 фактически являются арабскими цифрами. Люди, вероятно, знакомы с римскими цифрами, которые использовались людьми, которые говорили на латыни, в форме I, II, III, IV, V, VI и т. Д. En.wikipedia.org/wiki/Arabic_numerals ; en.wikipedia.org/wiki/Roman_numerals
@ kape123 :) уверен, что "123.456" не содержит цифр.
Ахмед Алехо
8
Примечание: это приводит к NPE для нулевого ввода. Кроме того, не работает с отрицательными числами или десятичными знаками.
gMale
2
Мне это нравится!! Я думаю, что это абсолютно для цифр. Не .,-
illusionJJ
Это как раз то, что я искал. Что-то простое, чтобы проверить только цифры 0-9. Я установил фильтр в объявлении моего EditText, но на всякий случай, если get был изменен или заменен в будущем, было бы хорошо иметь простую программную проверку.
Вы также можете использовать ссылку на метод: someString.chars (). AllMatch (Character :: isDigit)
Wienczny
3
Приятно, но все же он изобретает велосипед как почти все "решения" здесь. Кроме того, терпит неудачу при 'нуле' (как почти все другие).
Qben
8
Этот ответ является кратким, простым и читабельным. Вы можете почти прочитать это как английский - "chars all match digits". Не требует сторонних библиотек. Он не использует исключения в неисключительных случаях. Это должно стать принятым ответом.
Энди Томас,
14
Что это даст за "-1"?
Балас Немет
2
Не правильный ответ. Числовая строка может иметь нечисловые символы (например, "." Или "-") и при этом быть абсолютно числовой. Например, 0,5, -1 и 1000 все потерпят неудачу с этим ответом, и все же они являются абсолютно числовыми.
Симеон Г,
126
Как @CraigTP упомянул в своем превосходном ответе, у меня также есть похожие проблемы с производительностью при использовании Исключений для проверки, является ли строка числовой или нет. Так что я в конечном итоге разделить строку и использовать java.lang.Character.isDigit().
publicstaticboolean isNumeric(String str){for(char c : str.toCharArray()){if(!Character.isDigit(c))returnfalse;}returntrue;}
Согласно Javadoc , Character.isDigit(char)будет правильно распознавать нелатинские цифры. С точки зрения производительности, я думаю, что простое число сравнений N, где N - количество символов в строке, будет более вычислительно эффективным, чем сопоставление с регулярным выражением.
ОБНОВЛЕНИЕ: Как указал Жан-Франсуа Корбетт в комментарии, приведенный выше код будет проверять только положительные целые числа, которые покрывают большую часть моего варианта использования. Ниже приведен обновленный код, который корректно проверяет десятичные числа в соответствии с локалью по умолчанию, используемой в вашей системе, при условии, что десятичный разделитель встречается в строке только один раз.
publicstaticboolean isStringNumeric(String str ){DecimalFormatSymbols currentLocaleSymbols =DecimalFormatSymbols.getInstance();char localeMinusSign = currentLocaleSymbols.getMinusSign();if(!Character.isDigit( str.charAt(0))&& str.charAt(0)!= localeMinusSign )returnfalse;boolean isDecimalSeparatorFound =false;char localeDecimalSeparator = currentLocaleSymbols.getDecimalSeparator();for(char c : str.substring(1).toCharArray()){if(!Character.isDigit( c )){if( c == localeDecimalSeparator &&!isDecimalSeparatorFound ){
isDecimalSeparatorFound =true;continue;}returnfalse;}}returntrue;}
Разве десятичный разделитель также не приведет к сбою?
Жан-Франсуа Корбетт
1
@ Жан-Франсуа Корбетт: Хорошо, я обновил код новым, который принимает десятичные разделители.
Ибрагим Arief
2
Знак -ve не справляется с этой функцией?
java_mouse
3
Вызов toCharArray()создаст копию массива в объекте String, потому что строки являются неизменяемыми. Вероятно, быстрее использовать charAt(int index)метод непосредственно для объекта String.
Майк Кучера
2
Будет генерироваться StringIndexOutOfBoundsExceptionпри передаче строки длиной 0. Может быть исправлено с помощьюif(str.length() == 0) return false;
samgak
43
Библиотека гуавы Google обеспечивает хороший вспомогательный метод , чтобы сделать это: Ints.tryParse. Вы используете его как, Integer.parseIntно он возвращает, nullа не выбрасывает исключение, если строка не анализирует допустимое целое число. Обратите внимание, что он возвращает Integer, а не int, поэтому вы должны конвертировать / autobox обратно в int.
Тем не менее, в текущем выпуске - Guava r11 - он все еще помечен как @Beta.
Я не проверял это. Глядя на исходный код, есть некоторые издержки от многих проверок работоспособности, но в конце они используют Character.digit(string.charAt(idx)), похожий, но немного отличный от, ответ из @Ibrahim выше. В их реализации нет накладных расходов на обработку исключений.
Принятый ответ, тремя годами ранее, уже покрыт Number.isNumber().
Энди Томас,
Я так не думаю. Он был обновлен или оп изменил принятый ответ. Я помню, что принятый ответ не покрывал NumberUtils, поэтому я добавил свой ответ. Но спасибо за комментарий
Goot
2
@ Goot - История принятого ответа показывает, что Number.isNumber()присутствовало в первой версии ответа, датированной 24 сентября 12 года в 17:01.
Энди Томас,
@ Goot, это очень хорошо, так как в отличие от StringUtils, оно также включает проверку десятичного значения.
Хина Хуссейн
24
Почему все стремятся к решениям исключений / регулярных выражений?
Хотя я понимаю, что большинству людей хорошо использовать try / catch, но если вы хотите делать это часто ... это может быть очень сложным.
Здесь я использовал регулярное выражение, методы parseNumber () и метод поиска в массиве, чтобы увидеть, какой из них наиболее эффективен. На этот раз я посмотрел только на целые числа.
publicstaticboolean isNumericRegex(String str){if(str ==null)returnfalse;return str.matches("-?\\d+");}publicstaticboolean isNumericArray(String str){if(str ==null)returnfalse;char[] data = str.toCharArray();if(data.length <=0)returnfalse;int index =0;if(data[0]=='-'&& data.length >1)
index =1;for(; index < data.length; index++){if(data[index]<'0'|| data[index]>'9')// Character.isDigit() can go here too.returnfalse;}returntrue;}publicstaticboolean isNumericException(String str){if(str ==null)returnfalse;try{/* int i = */Integer.parseInt(str);}catch(NumberFormatException nfe){returnfalse;}returntrue;}
Результаты в скорости я получил:
Done with:for(int i =0; i <10000000; i++)...With only valid numbers ("59815833" and "-59815833"):Array numeric took 395.808192 ms [39.5808192 ns each]Regex took 2609.262595 ms [260.9262595 ns each]Exception numeric took 428.050207 ms [42.8050207 ns each]// Negative signArray numeric took 355.788273 ms [35.5788273 ns each]Regex took 2746.278466 ms [274.6278466 ns each]Exception numeric took 518.989902 ms [51.8989902 ns each]// Single value ("1")Array numeric took 317.861267 ms [31.7861267 ns each]Regex took 2505.313201 ms [250.5313201 ns each]Exception numeric took 239.956955 ms [23.9956955 ns each]// With Character.isDigit()Array numeric took 400.734616 ms [40.0734616 ns each]Regex took 2663.052417 ms [266.3052417 ns each]Exception numeric took 401.235906 ms [40.1235906 ns each]With invalid characters ("5981a5833" and "a"):Array numeric took 343.205793 ms [34.3205793 ns each]Regex took 2608.739933 ms [260.8739933 ns each]Exception numeric took 7317.201775 ms [731.7201775 ns each]// With a single character ("a")Array numeric took 291.695519 ms [29.1695519 ns each]Regex took 2287.25378 ms [228.725378 ns each]Exception numeric took 7095.969481 ms [709.5969481 ns each]Withnull:Array numeric took 214.663834 ms [21.4663834 ns each]Regex took 201.395992 ms [20.1395992 ns each]Exception numeric took 233.049327 ms [23.3049327 ns each]Exception numeric took 6603.669427 ms [660.3669427 ns each]if there is no if/null check
Отказ от ответственности: я не утверждаю, что эти методы оптимизированы на 100%, они просто для демонстрации данных
Исключения выигрывают тогда и только тогда, когда число составляет 4 символа или менее, и каждая строка всегда является числом ... в таком случае, зачем вообще чек?
Короче говоря, это очень больно, если вы часто сталкиваетесь с недопустимыми числами с помощью try / catch, что имеет смысл. Важное правило, которому я всегда следую, НИКОГДА не используйте try / catch для выполнения программы . Это пример почему.
Интересно, что простой if char <0 || > 9 было чрезвычайно просто написать, легко запомнить (и должно работать на нескольких языках) и выигрывает почти во всех тестовых сценариях.
Единственным недостатком является то, что я предполагаю, что Integer.parseInt () может обрабатывать числа не ASCII, в то время как метод поиска в массиве не делает.
Для тех, кто интересуется, почему я сказал, что легко запомнить массив символов один, если вы знаете, что нет отрицательных признаков, вы можете легко сойтись с чем-то сжатым, как это:
publicstaticboolean isNumericArray(String str){if(str ==null)returnfalse;for(char c : str.toCharArray())if(c <'0'|| c >'9')returnfalse;returntrue;
И наконец, в качестве заключительного замечания, мне было любопытно, что оператор присваивания в принятом примере набрал все голоса. Добавление в присвоение
double d =Double.parseDouble(...)
не только бесполезен, поскольку вы даже не используете это значение, но он тратит время обработки и увеличивает время выполнения на несколько наносекунд (что привело к увеличению тестов на 100-200 мс). Я не понимаю, почему кто-то так поступил, потому что это дополнительная работа по снижению производительности.
Вы могли бы подумать, что это будет оптимизировано ... хотя, возможно, я должен проверить байт-код и посмотреть, что делает компилятор. Это не объясняет, почему он всегда показывался мне более длинным, хотя, если он каким-то образом оптимизирован ... поэтому мне интересно, что происходит. Как примечание: под продолжительностью я имею в виду запуск теста для 10000000 итераций, и запуск этой программы несколько раз (10x +) всегда показывал, что он медленнее.
РЕДАКТИРОВАТЬ: Обновлен тест для Character.isDigit ()
Разве это не компилирует новое регулярное выражение каждый раз? Это не кажется очень эффективным.
Сэмюэль Эдвин Уорд
1
@SamuelEdwinWard Вот и вся причина, по которой я сделал этот пост ... Пример регулярного выражения использовал ответы других людей и показал, насколько он неэффективен. Даже если вы попытаетесь выполнить регулярное выражение с предварительной компиляцией заранее и только с его использованием, разница во времени составит: 2587 мс для регулярного выражения, которое я отправил от других пользователей, 950 мс при предварительной компиляции, 144 мс при выполнении этого как числовой массив (для 1 млн итераций одной и той же строки). Компиляция с опережением времени, очевидно, помогла бы, но, к сожалению, она все еще значительно уступает способу массива ... если только не существует какой-то безумной оптимизации, о которой я не знаю.
Вода
Полагать, что Regex делает вещи быстрее, почти заблуждение. Если это единственный поиск, да, я понял ... но я заметил, что эффективно написанный код на самом деле превосходит регулярное выражение настолько, что шокирует вас! Отличный пост @Water
Регулярное выражение CraigTP (показано выше) производит некоторые ложные срабатывания. Например, «23y4» будет считаться числом, потому что «.» соответствует любому символу, кроме десятичной точки.
Также он отклонит любое число с начальным «+»
Альтернатива, которая позволяет избежать этих двух незначительных проблем:
это вернется trueза один плюс "+"или минус "-", а falseдля"0."
user85421
Хороший улов на один плюс или минус. "0" действительный номер?
user872985
"0."допустимо Double.parseDouble()и является действительным литералом в соответствии с JLS ( §3.10.2 )!
user85421
Создание регулярных выражений также является дорогостоящим. Регулярное выражение должно быть создано один раз и использовано повторно
Даниил Нуриев
1
Вы должны изменить это наmatches("-?\\d+([.]\\d+)?")
Бобс
14
Мы можем попытаться заменить все числа из данной строки на (""), то есть пробел, и если после этого длина строки равна нулю, то мы можем сказать, что данная строка содержит только цифры. [Если вы нашли этот ответ полезным, пожалуйста, подумайте над его голосованием] Пример:
boolean isNumber(String str){if(str.length()==0)returnfalse;//To check if string is emptyif(str.charAt(0)=='-')
str = str.replaceFirst("-","");// for handling -ve numbersSystem.out.println(str);
str = str.replaceFirst("\\.","");//to check if it contains more than one decimal pointsif(str.length()==0)returnfalse;// to check if it is empty string after removing -ve sign and decimal pointSystem.out.println(str);return str.replaceAll("[0-9]","").length()==0;}
Улов все удобный метод , который можно использовать для анализа любой строки с любым типом парсера: isParsable(Object parser, String str). Парсер может быть Classили object. Это также позволит вам использовать пользовательские парсеры, которые вы написали и должны работать для любого сценария, например:
isParsable(Integer.class,"11");
isParsable(Double.class,"11.11");Object dateFormater =new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
isParsable(dateFormater,"2001.07.04 AD at 12:08:56 PDT");
Вот мой код с описанием методов.
import java.lang.reflect.*;/**
* METHOD: isParsable<p><p>
*
* This method will look through the methods of the specified <code>from</code> parameter
* looking for a public method name starting with "parse" which has only one String
* parameter.<p>
*
* The <code>parser</code> parameter can be a class or an instantiated object, eg:
* <code>Integer.class</code> or <code>new Integer(1)</code>. If you use a
* <code>Class</code> type then only static methods are considered.<p>
*
* When looping through potential methods, it first looks at the <code>Class</code> associated
* with the <code>parser</code> parameter, then looks through the methods of the parent's class
* followed by subsequent ancestors, using the first method that matches the criteria specified
* above.<p>
*
* This method will hide any normal parse exceptions, but throws any exceptions due to
* programmatic errors, eg: NullPointerExceptions, etc. If you specify a <code>parser</code>
* parameter which has no matching parse methods, a NoSuchMethodException will be thrown
* embedded within a RuntimeException.<p><p>
*
* Example:<br>
* <code>isParsable(Boolean.class, "true");<br>
* isParsable(Integer.class, "11");<br>
* isParsable(Double.class, "11.11");<br>
* Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");<br>
* isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");<br></code>
* <p>
*
* @param parser The Class type or instantiated Object to find a parse method in.
* @param str The String you want to parse
*
* @return true if a parse method was found and completed without exception
* @throws java.lang.NoSuchMethodException If no such method is accessible
*/publicstaticboolean isParsable(Object parser,String str){Class theClass =(parser instanceofClass?(Class)parser: parser.getClass());boolean staticOnly =(parser == theClass), foundAtLeastOne =false;Method[] methods = theClass.getMethods();// Loop over methodsfor(int index =0; index < methods.length; index++){Method method = methods[index];// If method starts with parse, is public and has one String parameter.// If the parser parameter was a Class, then also ensure the method is static. if(method.getName().startsWith("parse")&&(!staticOnly ||Modifier.isStatic(method.getModifiers()))&&Modifier.isPublic(method.getModifiers())&&
method.getGenericParameterTypes().length ==1&&
method.getGenericParameterTypes()[0]==String.class){try{
foundAtLeastOne =true;
method.invoke(parser, str);returntrue;// Successfully parsed without exception}catch(Exception exception){// If invoke problem, try a different method/*if(!(exception instanceof IllegalArgumentException) &&
!(exception instanceof IllegalAccessException) &&
!(exception instanceof InvocationTargetException))
continue; // Look for other parse methods*/// Parse method refuses to parse, look for another different methodcontinue;// Look for other parse methods}}}// No more accessible parse method could be found.if(foundAtLeastOne)returnfalse;elsethrownewRuntimeException(newNoSuchMethodException());}/**
* METHOD: willParse<p><p>
*
* A convienence method which calls the isParseable method, but does not throw any exceptions
* which could be thrown through programatic errors.<p>
*
* Use of {@link #isParseable(Object, String) isParseable} is recommended for use so programatic
* errors can be caught in development, unless the value of the <code>parser</code> parameter is
* unpredictable, or normal programtic exceptions should be ignored.<p>
*
* See {@link #isParseable(Object, String) isParseable} for full description of method
* usability.<p>
*
* @param parser The Class type or instantiated Object to find a parse method in.
* @param str The String you want to parse
*
* @return true if a parse method was found and completed without exception
* @see #isParseable(Object, String) for full description of method usability
*/publicstaticboolean willParse(Object parser,String str){try{return isParsable(parser, str);}catch(Throwable exception){returnfalse;}}
Эффективный подход, позволяющий избежать попыток отлова и обработки отрицательных чисел и научных обозначений.
Pattern PATTERN =Pattern.compile("^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$");publicstaticboolean isNumeric(String value ){return value !=null&& PATTERN.matcher( value ).matches();}
Обрабатывает отрицательные строковые значения ["-12,020000" -> "-12.02"]
Удаляет несколько точек ["-12.0.20.000" -> "-12.02"]
Никаких дополнительных библиотек, только стандартная Java
Ну вот...
publicclassNumUtils{/**
* Transforms a string to an integer. If no numerical chars returns a String "0".
*
* @param str
* @return retStr
*/staticString makeToInteger(String str){String s = str;double d;
d =Double.parseDouble(makeToDouble(s));int i =(int)(d +0.5D);String retStr =String.valueOf(i);System.out.printf(retStr +" ");return retStr;}/**
* Transforms a string to an double. If no numerical chars returns a String "0".
*
* @param str
* @return retStr
*/staticString makeToDouble(String str){Boolean dotWasFound =false;String orgStr = str;String retStr;int firstDotPos =0;Boolean negative =false;//check if str is nullif(str.length()==0){
str="0";}//check if first sign is "-"if(str.charAt(0)=='-'){
negative =true;}//check if str containg any number or else set the string to '0'if(!str.matches(".*\\d+.*")){
str ="0";}//Replace ',' with '.' (for some european users who use the ',' as decimal separator)
str = str.replaceAll(",",".");
str = str.replaceAll("[^\\d.]","");//Removes the any second dotsfor(int i_char =0; i_char < str.length(); i_char++){if(str.charAt(i_char)=='.'){
dotWasFound =true;
firstDotPos = i_char;break;}}if(dotWasFound){String befDot = str.substring(0, firstDotPos +1);String aftDot = str.substring(firstDotPos +1, str.length());
aftDot = aftDot.replaceAll("\\.","");
str = befDot + aftDot;}//Removes zeros from the beginingdouble uglyMethod =Double.parseDouble(str);
str =String.valueOf(uglyMethod);//Removes the .0
str = str.replaceAll("([0-9])\\.0+([^0-9]|$)","$1$2");
retStr = str;if(negative){
retStr ="-"+retStr;}return retStr;}staticboolean isNumeric(String str){try{double d =Double.parseDouble(str);}catch(NumberFormatException nfe){returnfalse;}returntrue;}}
Исключения являются дорогостоящими, но в этом случае RegEx занимает гораздо больше времени. Приведенный ниже код показывает простой тест двух функций - одна с использованием исключений и одна с использованием регулярных выражений. На моей машине версия RegEx в 10 раз медленнее, чем исключение.
import java.util.Date;publicclassIsNumeric{publicstaticboolean isNumericOne(String s){return s.matches("-?\\d+(\\.\\d+)?");//match a number with optional '-' and decimal. }publicstaticboolean isNumericTwo(String s){try{Double.parseDouble(s);returntrue;}catch(Exception e){returnfalse;}}publicstaticvoid main(String[] args){String test ="12345.F";long before =newDate().getTime();for(int x=0;x<1000000;++x){//isNumericTwo(test);
isNumericOne(test);}long after =newDate().getTime();System.out.println(after-before);}}
Вообще, я думаю, что этот вид кода будет использоваться для проверки таких вещей, как ввод ввода. В этом случае скорость не учитывается, и делать что-то такое уродливое, как неправильное создание исключения для проверки номера или отсутствия номера.
user872985
Возможно, нет. Типизированный ввод обычно проверяется компонентом пользовательского интерфейса, где ошибки могут быть немедленно показаны перед отправкой значения. Может быть более распространено проверять строки из больших входных текстовых файлов - там, где важна производительность. Цель в моем ответе здесь состоит в том, чтобы обратиться к утверждению «исключения являются медленными» в принятом ответе. Сложное регулярное выражение намного дороже. И в моем коде нет никакого «уродливого броска» - просто более быстрый способ выявления нарушений. При использовании метода «сначала проверяй, а потом вычисляй» вы делаете два прохода через вход: один для проверки, а затем для преобразования.
ChrisCantrell
5
// пожалуйста, проверьте код ниже
publicstaticboolean isDigitsOnly(CharSequence str){finalint len = str.length();for(int i =0; i < len; i++){if(!Character.isDigit(str.charAt(i))){returnfalse;}}returntrue;}
Вопрос говорит «числовой», который может включать нецелые значения.
дом
3
// only intpublicstaticboolean isNumber(int num){return(num >=48&& c <=57);// 0 - 9}// is type of number including . - e E publicstaticboolean isNumber(String s){boolean isNumber =true;for(int i =0; i < s.length()&& isNumber; i++){char c = s.charAt(i);
isNumber = isNumber &((c >='0'&& c <='9')||(c =='.')||(c =='e')||(c =='E')||(c ==''));}return isInteger;}// is type of number publicstaticboolean isInteger(String s){boolean isInteger =true;for(int i =0; i < s.length()&& isInteger; i++){char c = s.charAt(i);
isInteger = isInteger &((c >='0'&& c <='9'));}return isInteger;}publicstaticboolean isNumeric(String s){try{Double.parseDouble(s);returntrue;}catch(Exception e){returnfalse;}}
publicstaticboolean isNumericString(String input){boolean result =false;if(input !=null&& input.length()>0){char[] charArray = input.toCharArray();for(char c : charArray){if(c >='0'&& c <='9'){// it is a digit
result =true;}else{
result =false;break;}}}return result;}
Я изменил решение CraigTP, чтобы принять научную запись, а также точку и запятую в качестве десятичных разделителей.
^-?\d+([,\.]\d+)?([eE]-?\d+)?$
пример
var re =newRegExp("^-?\d+([,\.]\d+)?([eE]-?\d+)?$");
re.test("-6546");// true
re.test("-6546355e-4456");// true
re.test("-6546.355e-4456");// true, though debatable
re.test("-6546.35.5e-4456");// false
re.test("-6546.35.5e-4456.6");// false
Вот почему мне нравится подход Try * в .NET. В дополнение к традиционному методу Parse, похожему на Java, у вас также есть метод TryParse. Я не очень хорошо разбираюсь в синтаксисе Java (вне параметров?), Поэтому, пожалуйста, отнеситесь к следующему как к некоторому псевдокоду. Это должно прояснить концепцию, хотя.
boolean parseInteger(String s, out int number){try{
number =Integer.parseInt(myString);returntrue;}catch(NumberFormatException e){returnfalse;}}
Применение:
int num;if(parseInteger("23", out num)){// Do something with num.}
да, в Java нет «параметров out», и поскольку обертка Integer является неизменяемой (поэтому ее нельзя использовать в качестве допустимой ссылки для хранения выходных данных), разумной идиоматической опцией будет возвращение объекта Integer, который может быть нулевым, если анализ выполняется не смогли. Более уродливым вариантом может быть передача int [1] в качестве выходного параметра.
Фортран
Да, я помню обсуждение того, почему у Java нет выходных параметров. но возвращать Integer (как ноль, если необходимо) тоже было бы хорошо, я думаю, хотя я не знаю о производительности Java в отношении упаковки / распаковки.
OregonGhost
4
Мне нравится C # так же, как и следующему парню, но бесполезно добавлять фрагмент кода .NET C # для вопроса Java, когда функции не существуют в Java
Шейн,
Это создаст проблему с сонаром, если вы не зарегистрируете исключение
jmhostalet
2
Разобрать его (т.е. с Integer#parseInt ) и просто поймай исключение. знак равно
Для пояснения: функция parseInt проверяет, может ли она анализировать число в любом случае (очевидно), и если вы хотите разобрать его в любом случае, вы не получите никакого снижения производительности, фактически выполнив синтаксический анализ.
Если вы не хотите анализировать его (или анализировать очень, очень редко), вы, конечно, можете сделать это по-другому.
Я проиллюстрировал некоторые условия для проверки чисел и десятичных знаков без использования API,
Проверьте фиксированную длину 1-значный номер
Character.isDigit(char)
Проверьте номер фиксированной длины (допустим, длина равна 6)
String number ="132452";if(number.matches("([0-9]{6})"))System.out.println("6 digits number identified");
Проверьте число переменной длины между (предположим, что длина от 4 до 6)
// {n,m} n <= length <= mString number ="132452";if(number.matches("([0-9]{4,6})"))System.out.println("Number Identified between 4 to 6 length");String number ="132";if(!number.matches("([0-9]{4,6})"))System.out.println("Number not in length range or different format");
Отметьте десятичное число между переменной длиной (допустим, длина от 4 до 7)
// It will not count the '.' (Period) in lengthString decimal ="132.45";if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Numbers Identified between 4 to 7");String decimal ="1.12";if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Numbers Identified between 4 to 7");String decimal ="1234";if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Numbers Identified between 4 to 7");String decimal ="-10.123";if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Numbers Identified between 4 to 7");String decimal ="123..4";if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Decimal not in range or different format");String decimal ="132";if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Decimal not in range or different format");String decimal ="1.1";if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))System.out.println("Decimal not in range or different format");
Основываясь на других ответах, я написал свой, и он не использует шаблоны или синтаксический анализ с проверкой исключений.
Он проверяет максимум один знак минус и проверяет максимум один десятичный знак.
Вот несколько примеров и их результаты:
«1», «-1», «-1,5» и «-1,556» возвращают true
«1..5», «1A.5», «1.5D», «-» и «--1» возвращают false
Примечание. При необходимости вы можете изменить это, чтобы принять параметр Locale и передать его в вызовы DecimalFormatSymbols.getInstance (), чтобы использовать конкретный Locale вместо текущего.
publicstaticboolean isNumeric(finalString input){//Check for null or blank stringif(input ==null|| input.isBlank())returnfalse;//Retrieve the minus sign and decimal separator characters from the current Localefinal var localeMinusSign =DecimalFormatSymbols.getInstance().getMinusSign();final var localeDecimalSeparator =DecimalFormatSymbols.getInstance().getDecimalSeparator();//Check if first character is a minus signfinal var isNegative = input.charAt(0)== localeMinusSign;//Check if string is not just a minus signif(isNegative && input.length()==1)returnfalse;
var isDecimalSeparatorFound =false;//If the string has a minus sign ignore the first characterfinal var startCharIndex = isNegative ?1:0;//Check if each character is a number or a decimal separator//and make sure string only has a maximum of one decimal separatorfor(var i = startCharIndex; i < input.length(); i++){if(!Character.isDigit(input.charAt(i))){if(input.charAt(i)== localeDecimalSeparator &&!isDecimalSeparatorFound){
isDecimalSeparatorFound =true;}elsereturnfalse;}}returntrue;}
Вот два метода, которые могут работать. (Без использования исключений). Примечание: Java является передачей по значению по умолчанию, а значение String является адресом данных объекта String. Итак, когда вы делаете
stringNumber = stringNumber.replaceAll(" ","");
Вы изменили входное значение, чтобы не было пробелов. Вы можете удалить эту строку, если хотите.
Вот еще один метод на случай, если вы хотите разрешить операции с плавающей точкой. Этот метод якобы позволяет числам в форме проходить 1,123,123,123,123,123.123, которые я только что сделал, и я думаю, что требуется дальнейшее тестирование, чтобы убедиться, что оно работает.
privateboolean isValidStringTrueNumber(String stringNumber){if(stringNumber.isEmpty()){returnfalse;}
stringNumber = stringNumber.replaceAll(" ","");int countOfDecimalPoint =0;boolean decimalPointPassed =false;boolean commaFound =false;int countOfDigitsBeforeDecimalPoint =0;int countOfDigitsAfterDecimalPoint =0;int commaCounter=0;int countOfDigitsBeforeFirstComma =0;char[] charNumber = stringNumber.toCharArray();for(int i =0; i<charNumber.length ;i++){if((commaCounter>3)||(commaCounter<0)){returnfalse;}if(!Character.isDigit(charNumber[i]))//Char is not a digit.{if(charNumber[i]==','){if(decimalPointPassed){returnfalse;}
commaFound =true;//check that next three chars are only digits.
commaCounter +=3;}elseif(charNumber[i]=='.'){
decimalPointPassed =true;
countOfDecimalPoint++;}else{returnfalse;}}else//Char is a digit.{if((commaCounter>=0)&&(commaFound)){if(!decimalPointPassed){
commaCounter--;}}if(!commaFound){
countOfDigitsBeforeFirstComma++;}if(!decimalPointPassed){
countOfDigitsBeforeDecimalPoint++;}else{
countOfDigitsAfterDecimalPoint++;}}}if((commaFound)&&(countOfDigitsBeforeFirstComma>3)){returnfalse;}if(countOfDecimalPoint>1){returnfalse;}if((decimalPointPassed)&&((countOfDigitsBeforeDecimalPoint==0)||(countOfDigitsAfterDecimalPoint==0))){returnfalse;}returntrue;}
О, хороший вопрос. Я думаю, что это работает только целые числа нормального типа. Метод изначально был создан для фильтрации входных телефонных номеров и подсчета номеров.
Integer.parseInt()
не смогут анализировать мобильные номераNumberFormatException
.Ответы:
С Apache Commons Lang 3.5 и выше:
NumberUtils.isCreatable
илиStringUtils.isNumeric
.С Apache Commons Lang 3.4 и ниже:
NumberUtils.isNumber
илиStringUtils.isNumeric
.Вы также можете использовать,
StringUtils.isNumericSpace
который возвращаетtrue
пустые строки и игнорирует внутренние пробелы в строке. Другой способ заключается в использовании,NumberUtils.isParsable
который в основном проверяет число, доступное для анализа в соответствии с Java. (Связанные javadocs содержат подробные примеры для каждого метода.)источник
StringUtils.isNumeric()
вероятно, здесь не подходит, так как он проверяет, является ли строка последовательностью цифр. Было бы хорошо для большинства целых, но не для чисел с десятичными числами, разделителями групп и т. Д.StringUtils
не поддерживает начальные знаки, но вы должны проверитьNumberUtils.isCreatable
, он правильно поддерживает негативы.Как правило, это делается с помощью простой пользовательской функции (например, «isNumeric»).
Что-то вроде:
Однако, если вы часто вызываете эту функцию и ожидаете, что многие проверки не пройдут из-за того, что они не являются числом, производительность этого механизма будет невелика, поскольку вы полагаетесь на исключения, создаваемые для каждой ошибки, что довольно дорогая операция.
Альтернативный подход может состоять в том, чтобы использовать регулярное выражение для проверки действительности числа:
Будьте осторожны с вышеупомянутым механизмом RegEx, так как он потерпит неудачу, если вы используете неарабские цифры (то есть цифры, отличные от 0 до 9). Это связано с тем, что часть "\ d" в RegEx будет совпадать только с [0-9] и фактически не будет численно известна на международном уровне. (Спасибо OregonGhost за указание на это!)
Или даже другой альтернативой является использование встроенного в Java объекта java.text.NumberFormat, чтобы проверить, находится ли после синтаксического анализа строки позиция парсера в конце строки. Если это так, мы можем предположить, что вся строка числовая:
источник
.
в вашем регулярном выражении будет соответствовать любой символ, а не только символ десятичного разделителя.Если вы на Android, то вы должны использовать:
документацию можно найти здесь
будь проще . в основном каждый может «перепрограммировать» (тоже самое).
источник
.
,-
Java 8 лямбда-выражений.
источник
Как @CraigTP упомянул в своем превосходном ответе, у меня также есть похожие проблемы с производительностью при использовании Исключений для проверки, является ли строка числовой или нет. Так что я в конечном итоге разделить строку и использовать
java.lang.Character.isDigit()
.Согласно Javadoc ,
Character.isDigit(char)
будет правильно распознавать нелатинские цифры. С точки зрения производительности, я думаю, что простое число сравнений N, где N - количество символов в строке, будет более вычислительно эффективным, чем сопоставление с регулярным выражением.ОБНОВЛЕНИЕ: Как указал Жан-Франсуа Корбетт в комментарии, приведенный выше код будет проверять только положительные целые числа, которые покрывают большую часть моего варианта использования. Ниже приведен обновленный код, который корректно проверяет десятичные числа в соответствии с локалью по умолчанию, используемой в вашей системе, при условии, что десятичный разделитель встречается в строке только один раз.
источник
toCharArray()
создаст копию массива в объекте String, потому что строки являются неизменяемыми. Вероятно, быстрее использоватьcharAt(int index)
метод непосредственно для объекта String.StringIndexOutOfBoundsException
при передаче строки длиной 0. Может быть исправлено с помощьюif(str.length() == 0) return false;
Библиотека гуавы Google обеспечивает хороший вспомогательный метод , чтобы сделать это:
Ints.tryParse
. Вы используете его как,Integer.parseInt
но он возвращает,null
а не выбрасывает исключение, если строка не анализирует допустимое целое число. Обратите внимание, что он возвращает Integer, а не int, поэтому вы должны конвертировать / autobox обратно в int.Пример:
Тем не менее, в текущем выпуске - Guava r11 - он все еще помечен как @Beta.
Я не проверял это. Глядя на исходный код, есть некоторые издержки от многих проверок работоспособности, но в конце они используют
Character.digit(string.charAt(idx))
, похожий, но немного отличный от, ответ из @Ibrahim выше. В их реализации нет накладных расходов на обработку исключений.источник
Не используйте исключения для проверки ваших значений. Вместо этого используйте Util libs, как apache NumberUtils:
Редактировать :
Обратите внимание, что если ваша строка начинается с 0, NumberUtils будет интерпретировать ваше значение как шестнадцатеричное.
источник
Number.isNumber()
.Number.isNumber()
присутствовало в первой версии ответа, датированной 24 сентября 12 года в 17:01.Почему все стремятся к решениям исключений / регулярных выражений?
Хотя я понимаю, что большинству людей хорошо использовать try / catch, но если вы хотите делать это часто ... это может быть очень сложным.
Здесь я использовал регулярное выражение, методы parseNumber () и метод поиска в массиве, чтобы увидеть, какой из них наиболее эффективен. На этот раз я посмотрел только на целые числа.
Результаты в скорости я получил:
Отказ от ответственности: я не утверждаю, что эти методы оптимизированы на 100%, они просто для демонстрации данных
Исключения выигрывают тогда и только тогда, когда число составляет 4 символа или менее, и каждая строка всегда является числом ... в таком случае, зачем вообще чек?
Короче говоря, это очень больно, если вы часто сталкиваетесь с недопустимыми числами с помощью try / catch, что имеет смысл. Важное правило, которому я всегда следую, НИКОГДА не используйте try / catch для выполнения программы . Это пример почему.
Интересно, что простой if char <0 || > 9 было чрезвычайно просто написать, легко запомнить (и должно работать на нескольких языках) и выигрывает почти во всех тестовых сценариях.
Единственным недостатком является то, что я предполагаю, что Integer.parseInt () может обрабатывать числа не ASCII, в то время как метод поиска в массиве не делает.
Для тех, кто интересуется, почему я сказал, что легко запомнить массив символов один, если вы знаете, что нет отрицательных признаков, вы можете легко сойтись с чем-то сжатым, как это:
И наконец, в качестве заключительного замечания, мне было любопытно, что оператор присваивания в принятом примере набрал все голоса. Добавление в присвоение
не только бесполезен, поскольку вы даже не используете это значение, но он тратит время обработки и увеличивает время выполнения на несколько наносекунд (что привело к увеличению тестов на 100-200 мс). Я не понимаю, почему кто-то так поступил, потому что это дополнительная работа по снижению производительности.
Вы могли бы подумать, что это будет оптимизировано ... хотя, возможно, я должен проверить байт-код и посмотреть, что делает компилятор. Это не объясняет, почему он всегда показывался мне более длинным, хотя, если он каким-то образом оптимизирован ... поэтому мне интересно, что происходит. Как примечание: под продолжительностью я имею в виду запуск теста для 10000000 итераций, и запуск этой программы несколько раз (10x +) всегда показывал, что он медленнее.
РЕДАКТИРОВАТЬ: Обновлен тест для Character.isDigit ()
источник
Регулярное выражение CraigTP (показано выше) производит некоторые ложные срабатывания. Например, «23y4» будет считаться числом, потому что «.» соответствует любому символу, кроме десятичной точки.
Также он отклонит любое число с начальным «+»
Альтернатива, которая позволяет избежать этих двух незначительных проблем:
источник
true
за один плюс"+"
или минус"-"
, аfalse
для"0."
"0."
допустимоDouble.parseDouble()
и является действительным литералом в соответствии с JLS ( §3.10.2 )!matches("-?\\d+([.]\\d+)?")
Мы можем попытаться заменить все числа из данной строки на (""), то есть пробел, и если после этого длина строки равна нулю, то мы можем сказать, что данная строка содержит только цифры. [Если вы нашли этот ответ полезным, пожалуйста, подумайте над его голосованием] Пример:
источник
""
это число , но"3.14"
и"-1"
не?Вы можете использовать
NumberFormat#parse
:источник
value
.Если вы используете Java для разработки Android-приложения, вы можете использовать функцию TextUtils.isDigitsOnly .
источник
Здесь был мой ответ на проблему.
Улов все удобный метод , который можно использовать для анализа любой строки с любым типом парсера:
isParsable(Object parser, String str)
. Парсер может бытьClass
илиobject
. Это также позволит вам использовать пользовательские парсеры, которые вы написали и должны работать для любого сценария, например:Вот мой код с описанием методов.
источник
Чтобы сопоставить только положительные целые числа из десяти базовых чисел, которые содержат только цифры ASCII, используйте:
источник
Эффективный подход, позволяющий избежать попыток отлова и обработки отрицательных чисел и научных обозначений.
источник
Вот мой класс для проверки, является ли строка числовой. Также исправляет числовые строки:
Особенности:
Ну вот...
источник
Вот еще один пример обновленного регулярного выражения "CraigTP" с большим количеством проверок.
источник
Исключения являются дорогостоящими, но в этом случае RegEx занимает гораздо больше времени. Приведенный ниже код показывает простой тест двух функций - одна с использованием исключений и одна с использованием регулярных выражений. На моей машине версия RegEx в 10 раз медленнее, чем исключение.
источник
// пожалуйста, проверьте код ниже
источник
источник
Вот простой пример для этой проверки:
источник
Вы можете использовать объект java.util.Scanner.
источник
Я изменил решение CraigTP, чтобы принять научную запись, а также точку и запятую в качестве десятичных разделителей.
пример
источник
Вот почему мне нравится подход Try * в .NET. В дополнение к традиционному методу Parse, похожему на Java, у вас также есть метод TryParse. Я не очень хорошо разбираюсь в синтаксисе Java (вне параметров?), Поэтому, пожалуйста, отнеситесь к следующему как к некоторому псевдокоду. Это должно прояснить концепцию, хотя.
Применение:
источник
Разобрать его (т.е. с
Integer#parseInt
) и просто поймай исключение. знак равноДля пояснения: функция parseInt проверяет, может ли она анализировать число в любом случае (очевидно), и если вы хотите разобрать его в любом случае, вы не получите никакого снижения производительности, фактически выполнив синтаксический анализ.
Если вы не хотите анализировать его (или анализировать очень, очень редко), вы, конечно, можете сделать это по-другому.
источник
Вы можете использовать NumberUtils.isCreatable () из Apache Commons Lang .
Поскольку NumberUtils.isNumber будет устаревшим в версии 4.0, используйте вместо него NumberUtils.isCreatable ().
источник
Java 8 Stream, лямбда-выражение, функциональный интерфейс
Все случаи обрабатываются ( пустая строка, пустая строка и т. Д. )
источник
Я проиллюстрировал некоторые условия для проверки чисел и десятичных знаков без использования API,
Проверьте фиксированную длину 1-значный номер
Проверьте номер фиксированной длины (допустим, длина равна 6)
Проверьте число переменной длины между (предположим, что длина от 4 до 6)
Отметьте десятичное число между переменной длиной (допустим, длина от 4 до 7)
Надеюсь, это поможет многим.
источник
Основываясь на других ответах, я написал свой, и он не использует шаблоны или синтаксический анализ с проверкой исключений.
Он проверяет максимум один знак минус и проверяет максимум один десятичный знак.
Вот несколько примеров и их результаты:
«1», «-1», «-1,5» и «-1,556» возвращают true
«1..5», «1A.5», «1.5D», «-» и «--1» возвращают false
Примечание. При необходимости вы можете изменить это, чтобы принять параметр Locale и передать его в вызовы DecimalFormatSymbols.getInstance (), чтобы использовать конкретный Locale вместо текущего.
источник
Вот два метода, которые могут работать. (Без использования исключений). Примечание: Java является передачей по значению по умолчанию, а значение String является адресом данных объекта String. Итак, когда вы делаете
Вы изменили входное значение, чтобы не было пробелов. Вы можете удалить эту строку, если хотите.
Вот еще один метод на случай, если вы хотите разрешить операции с плавающей точкой. Этот метод якобы позволяет числам в форме проходить 1,123,123,123,123,123.123, которые я только что сделал, и я думаю, что требуется дальнейшее тестирование, чтобы убедиться, что оно работает.
источник