Możesz także użyć, StringUtils.isNumericSpacektóre zwraca truepuste ciągi i ignoruje wewnętrzne spacje w ciągu. Innym sposobem jest użycie, NumberUtils.isParsablektóre zasadniczo sprawdza, czy liczba jest możliwa do parsowania zgodnie z Javą. (Połączone javadocs zawierają szczegółowe przykłady dla każdej metody.)
StringUtils.isNumeric()prawdopodobnie nie byłoby to właściwe tutaj, ponieważ sprawdza tylko, czy ciąg znaków jest ciągiem cyfr. Byłoby dobrze dla większości liczb całkowitych, ale nie dla liczb z ułamkami dziesiętnymi, separatorów grup itp.
Jeff Mercado
42
wymyśl koło na nowo, ponieważ nie dołączasz całej biblioteki, ponieważ potrzebujesz funkcji 3-liniowej w jednym miejscu.
dalvarezmartinez1
12
Czy naprawdę warto jednak dodać całą bibliotekę dla tej funkcji? Oczywiście, jeśli jest używany z innymi rzeczami, które są świetne, ale prawdopodobnie jest to przesada, biorąc pod uwagę, że ludzie rozwiązali to w jednym wierszu kodu.
Woda
7
Nie działa z negatywami. A połowa wszystkich liczb jest ujemna, więc .....
Jeśli jednak często wywołujesz tę funkcję i oczekujesz, że wiele kontroli zakończy się niepowodzeniem z powodu braku bycia liczbą, to działanie tego mechanizmu nie będzie świetne, ponieważ polegasz na wyjątkach zgłaszanych dla każdej awarii, co jest dość kosztowną operacją.
Alternatywnym podejściem może być użycie wyrażenia regularnego w celu sprawdzenia ważności bycia liczbą:
publicstaticboolean isNumeric(String str){return str.matches("-?\\d+(\\.\\d+)?");//match a number with optional '-' and decimal.}
Uważaj jednak na powyższy mechanizm RegEx, ponieważ zawiedzie, jeśli używasz cyfr spoza arabskiego (tj. Cyfr od 0 do 9). Wynika to z faktu, że część „\ d” RegEx będzie pasować tylko do [0-9] i faktycznie nie jest międzynarodowo świadoma liczbowo. (Podziękowania dla OregonGhost za zwrócenie na to uwagi!)
Lub jeszcze inną alternatywą jest użycie wbudowanego obiektu Java java.text.NumberFormat, aby sprawdzić, czy po analizie ciągu pozycja parsera znajduje się na końcu ciągu. Jeśli tak, możemy założyć, że cały ciąg jest liczbowy:
Czy \ d w Java Regex pasuje tylko do cyfr łacińskich? Jeśli jest to wyrażenie regularne
OregonGhost
3
rozwiązanie numberFormatter jest prawdopodobnie tylko nieznacznie lepsze niż wyłapanie wyjątku NumberFormatException jeden. Podejrzewam, że najlepszym sposobem jest użycie wyrażenia regularnego.
Chii,
11
Zauważ, że .w wyrażeniu regularnym będzie pasować dowolny znak, a nie tylko separator dziesiętny.
jqno
9
+1 za realizację kosztu wypróbowania / złapania. To naprawdę okropne podejście do używania na dłuższą metę do wielokrotnego użytku, ale tak naprawdę utknęliśmy z tym w Javie.
demongolem
5
Zauważ, że nie ma czegoś takiego jak „cyfry łacińskie”, a cyfry 0–9 są w rzeczywistości cyframi arabskimi. Ludzie prawdopodobnie znają cyfry rzymskie, których używali ludzie, którzy mówili po łacinie, w postaci I, II, III, IV, V, VI itp. En.wikipedia.org/wiki/Arabic_numerals ; en.wikipedia.org/wiki/Roman_numerals
Uwaga: powoduje to NPE dla wejścia zerowego. Ponadto nie działa z liczbami ujemnymi lub dziesiętnymi.
gMale,
2
Lubię to!! Myślę, że to jest absolutnie dla cyfr. Nie .,-
iluzja
Właśnie tego szukałem. Coś prostego do sprawdzenia tylko dla cyfr 0–9. Ustawiłem filtr w deklaracji mojego EditText, ale na wypadek, gdyby zmiany zostały zmienione lub zastąpione w drodze, miło jest mieć również prostą kontrolę programową.
Możesz także użyć odwołania do metody: someString.chars (). AllMatch (Character :: isDigit)
Wienczny
3
Fajnie, ale wciąż wymyśla koło na nowo, tak jak prawie wszystkie „rozwiązania” tutaj. Również kończy się niepowodzeniem na „null” (jak prawie wszystkie inne).
qben
8
Ta odpowiedź jest zwięzła, prosta i czytelna. Można go prawie odczytać jak po angielsku - „znaki wszystkich pasujących cyfr”. Nie wymaga bibliotek stron trzecich. Nie stosuje wyjątków w wyjątkowych przypadkach. To powinno stać się przyjętą odpowiedzią.
Andy Thomas
14
Co będzie produkować dla „-1”?
Balázs Németh
2
Niewłaściwa odpowiedź. Ciąg liczbowy może zawierać znaki nienumeryczne (np. „.” Lub „-”) i nadal być doskonale numeryczny. Na przykład 0,5, -1 i 1000 nie powiedzie się z tą odpowiedzią, a mimo to są doskonale numeryczne.
Simeon G
125
Jak wspomniał @CraigTP w swojej doskonałej odpowiedzi, mam podobne obawy dotyczące wydajności przy użyciu wyjątków w celu sprawdzenia, czy łańcuch jest liczbowy, czy nie. W rezultacie dzielę ciąg i używam java.lang.Character.isDigit().
publicstaticboolean isNumeric(String str){for(char c : str.toCharArray()){if(!Character.isDigit(c))returnfalse;}returntrue;}
Według Javadoc , Character.isDigit(char)poprawnie rozpoznaje niełacińskie cyfr. Pod względem wydajności myślę, że prosta liczba N porównań, w których N jest liczbą znaków w łańcuchu, byłaby bardziej wydajna obliczeniowo niż dopasowanie wyrażenia regularnego.
AKTUALIZACJA: Jak zauważył Jean-François Corbett w komentarzu, powyższy kod sprawdziłby tylko liczby całkowite dodatnie, co obejmuje większość mojego przypadku użycia. Poniżej znajduje się zaktualizowany kod, który poprawnie sprawdza poprawność liczb dziesiętnych zgodnie z domyślnymi ustawieniami narodowymi używanymi w systemie, przy założeniu, że separator dziesiętny występuje tylko raz w ciągu.
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;}
Czy separator dziesiętny również nie spowoduje tego?
Jean-François Corbett
1
@ Jean-FrançoisCorbett: Dobrze, zaktualizowałem kod do nowszego, który akceptuje separatory dziesiętne.
Ibrahim Arief
2
Czy znak -ve nie spełnia tej funkcji?
java_mouse
3
Wywołanie toCharArray()spowoduje utworzenie kopii tablicy w obiekcie String, ponieważ ciągi są niezmienne. Prawdopodobnie szybciej użyć charAt(int index)metody bezpośrednio na obiekcie String.
Mike Kucera,
2
Wygeneruje StringIndexOutOfBoundsExceptionkiedy przeszedł ciąg o długości 0. Może być zamocowaneif(str.length() == 0) return false;
samgak
43
Biblioteka Guava Google zapewnia miły metody pomocnika, aby to zrobić: Ints.tryParse. Używasz go w ten sposób, Integer.parseIntale zwraca on nullzamiast rzucać wyjątek, jeśli ciąg nie parsuje prawidłowej liczby całkowitej. Zauważ, że zwraca Integer, a nie int, więc musisz przekonwertować / autobox z powrotem na int.
Jednak od obecnego wydania - Guava r11 - nadal jest oznaczony @Beta.
Nie porównałem tego. Patrząc na kod źródłowy, pojawia się pewien narzut związany z dużą ilością sprawdzania poprawności, ale w końcu używają Character.digit(string.charAt(idx))podobnej, ale nieco innej niż odpowiedź z @Ibrahim powyżej. W ich implementacji nie ma wyjątku obsługa kosztów ogólnych pod przykryciem.
Przyjęta odpowiedź sprzed trzech lat już obejmuje Number.isNumber().
Andy Thomas
Nie wydaje mi się Został zaktualizowany lub zmienił zaakceptowaną odpowiedź. Pamiętam, że zaakceptowana odpowiedź nie obejmowała NumberUtils, dlatego dodałem swoją odpowiedź. Ale dziękuję za komentarz
Goot
2
@Goot - Historia zaakceptowanej odpowiedzi pokazuje, że Number.isNumber()była obecna od pierwszej wersji odpowiedzi, datowanej na 24 września 12 o 17:01.
Andy Thomas
@Goot, jest to całkiem dobre, ponieważ obejmuje również sprawdzanie wartości dziesiętnej, w przeciwieństwie do StringUtils.
Heena Hussain
24
Dlaczego wszyscy naciskają na rozwiązania wyjątkowe / wyrażenia regularne?
Chociaż rozumiem, że większość ludzi nie ma nic przeciwko używaniu try / catch, jeśli chcesz to robić często ... może to być bardzo obciążające.
To, co zrobiłem tutaj, to wzięcie wyrażenia regularnego, metod parseNumber () i metody przeszukiwania tablicy, aby sprawdzić, która z nich była najbardziej wydajna. Tym razem spojrzałem tylko na liczby całkowite.
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;}
Wyniki, które uzyskałem, były następujące:
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
Oświadczenie: Nie twierdzę, że te metody są w 100% zoptymalizowane, służą jedynie do demonstracji danych
Wyjątki wygrane wtedy i tylko wtedy, gdy liczba ma 4 znaki lub mniej, a każdy ciąg jest zawsze liczbą ... w takim przypadku, po co w ogóle mieć czek?
Krótko mówiąc, jest to bardzo bolesne, jeśli często próbujesz złapać nieprawidłowe liczby za pomocą try / catch, co ma sens. Ważną zasadą, której zawsze przestrzegam jest NIGDY nie używaj try / catch do przebiegu programu . To jest przykład dlaczego.
Co ciekawe, prosty jeśli char <0 || > 9 było niezwykle łatwe do napisania, łatwe do zapamiętania (i powinno działać w wielu językach) i wygrywa prawie wszystkie scenariusze testowe.
Jedynym minusem jest to, że zgaduję, że Integer.parseInt () może obsługiwać liczby inne niż ASCII, podczas gdy metoda wyszukiwania tablicowego nie.
Dla tych, którzy zastanawiają się, dlaczego powiedziałem, że łatwo jest zapamiętać tablicę znaków, jeśli wiesz, że nie ma żadnych negatywnych znaków, możesz łatwo uciec od czegoś skondensowanego:
publicstaticboolean isNumericArray(String str){if(str ==null)returnfalse;for(char c : str.toCharArray())if(c <'0'|| c >'9')returnfalse;returntrue;
Wreszcie, jako ostatnia uwaga, byłem ciekawy operatora przypisania w przyjętym przykładzie z wszystkimi głosami. Dodanie w przypisaniu
double d =Double.parseDouble(...)
jest nie tylko bezużyteczny, ponieważ nawet nie używasz tej wartości, ale marnuje czas przetwarzania i wydłuża czas działania o kilka nanosekund (co doprowadziło do wzrostu testów o 100-200 ms). Nie rozumiem, dlaczego ktoś miałby to zrobić, ponieważ w rzeczywistości jest to dodatkowa praca w celu zmniejszenia wydajności.
Można by pomyśleć, że zostałby zoptymalizowany ... chociaż może powinienem sprawdzić kod bajtowy i zobaczyć, co robi kompilator. To nie tłumaczy, dlaczego zawsze wydawało mi się, że jest dłuższe, jeśli jest w jakiś sposób zoptymalizowane ... dlatego zastanawiam się, co się dzieje. Uwaga: przez dłuższy czas mam na myśli uruchomienie testu dla iteracji 10000000, a wielokrotne uruchomienie tego programu (10x +) zawsze pokazało, że jest wolniejszy.
EDYCJA: Zaktualizowano test dla Character.isDigit ()
Czy to nie kompiluje za każdym razem nowego wyrażenia regularnego? To nie wydaje się bardzo skuteczne.
Samuel Edwin Ward,
1
@SamuelEdwinWard To cały powód, dla którego napisałem ten post ... przykład wyrażenia regularnego wykorzystał odpowiedzi innych osób i pokazał, jak mało wydajny. Nawet jeśli spróbujesz regex z kompilacją z wyprzedzeniem i tylko przy użyciu tego, różnice czasowe wynoszą: 2587 ms dla wyrażenia regularnego, które opublikowałem od innych udostępnionych osób, 950 ms przy kompilacji z wyprzedzeniem, 144 ms podczas robienia tego jako tablica numeryczna (dla 1 miliona iteracji tego samego łańcucha). Kompilacja z wyprzedzeniem oczywiście pomogłaby, ale niestety nadal jest znacznie gorsza od sposobu tablicowego ... chyba że istnieje jakaś szalona optymalizacja, o której nie wiem.
Woda
Wiara w to, że Regex przyspiesza sprawę, jest niemal błędem. Jeśli jest to jednorazowe wyszukiwanie, tak, rozumiem ... ale zauważyłem, że skutecznie napisany kod faktycznie przewyższa wyrażenia regularne na tyle, aby cię zszokować! Świetny post @Water
Wyrażenie regularne CraigTP (pokazane powyżej) powoduje pewne fałszywe alarmy. Np. „23y4” będzie liczone jako liczba, ponieważ „.” dopasowuje dowolny znak inny niż przecinek dziesiętny.
Odrzuci także dowolną liczbę z wiodącym „+”
Alternatywą, która pozwala uniknąć tych dwóch drobnych problemów, jest
to zwróci truepojedynczy plus "+"lub minus "-", a falsedla"0."
user85421
Dobry połów na pojedynczym plusie lub minusie. Jest „0” prawidłowy numer?
user872985,
"0."jest ważny Double.parseDouble()i jest prawidłowym literałem zgodnie z JLS ( §3.10.2 )!
user85421,
Tworzenie wyrażeń regularnych jest również kosztowne. Wyrażenie regularne należy utworzyć raz i użyć ponownie
Daniel Nuriyev
1
powinieneś to zmienić namatches("-?\\d+([.]\\d+)?")
Bobs
14
Możemy spróbować zastąpić wszystkie liczby z podanego ciągu ciągiem („”), tj. Spacją, a jeśli po tym czasie długość łańcucha wyniesie zero, możemy powiedzieć, że podany ciąg zawiera tylko liczby. [Jeśli uznasz, że ta odpowiedź była pomocna, zastanów się nad jej głosowaniem] Przykład:
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;}
Łapacz wszystkim metoda wygoda, które można wykorzystać do analizowania dowolny ciąg z dowolnym typem parsera: isParsable(Object parser, String str). Analizator składni może być a Classlub an object. Umożliwi to również użycie napisanych przez Ciebie niestandardowych parserów i powinno działać na zawsze, np .:
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");
Oto mój kod wraz z opisami metod.
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;}}
Skuteczne podejście pozwalające uniknąć prób połowu i obsługi liczb ujemnych i notacji naukowej.
Pattern PATTERN =Pattern.compile("^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$");publicstaticboolean isNumeric(String value ){return value !=null&& PATTERN.matcher( value ).matches();}
Obsługuje ujemne wartości ciągu [„-12,020000” -> „-12.02”]
Usuwa wiele kropek [„-12.0.20.000” -> „-12.02”]
Bez dodatkowych bibliotek, tylko standardowa Java
Proszę bardzo...
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;}}
Wyjątki są drogie, ale w tym przypadku RegEx trwa znacznie dłużej. Poniższy kod pokazuje prosty test dwóch funkcji - jednej z wyjątkami i drugiej z wyrażeniem regularnym. Na moim komputerze wersja RegEx jest 10 razy wolniejsza niż wyjątek.
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);}}
Ogólnie rzecz biorąc, myślę, że ten rodzaj kodu byłby używany do sprawdzania takich rzeczy, jak wprowadzanie tekstu na klawiaturze. W takim przypadku szybkość nie jest brana pod uwagę, a robienie czegoś tak brzydkiego, jak rzucanie wyjątku w celu sprawdzenia liczby lub liczby nie jest błędne.
user872985,
Może nie. Wpisane dane są generalnie sprawdzane przez komponent interfejsu użytkownika, w którym błędy mogą być natychmiast pokazywane przed przesłaniem wartości. Częstsze może być sprawdzanie poprawności ciągów z dużych wejściowych plików tekstowych - tam, gdzie liczy się wydajność. Celem mojej odpowiedzi tutaj jest zajęcie się stwierdzeniem „wyjątki są powolne” w przyjętej odpowiedzi. Złożone wyrażenie regularne jest znacznie droższe. W moim kodzie nie ma w ogóle „brzydkiego rzutu” - to po prostu szybszy sposób wykrywania naruszeń. W metodzie „najpierw sprawdź, a następnie oblicz” dokonujesz dwóch przejść przez dane wejściowe: jeden do weryfikacji, a drugi do konwersji.
ChrisCantrell,
5
// sprawdź poniższy kod
publicstaticboolean isDigitsOnly(CharSequence str){finalint len = str.length();for(int i =0; i < len; i++){if(!Character.isDigit(str.charAt(i))){returnfalse;}}returntrue;}
Pytanie brzmi „numeryczny”, który może obejmować wartości niecałkowite.
rghome
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;}
Zmodyfikowałem rozwiązanie CraigTP, aby akceptować notację naukową oraz kropkę i przecinek jako separatory dziesiętne
^-?\d+([,\.]\d+)?([eE]-?\d+)?$
przykład
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
Dlatego podoba mi się podejście Try * w .NET. Oprócz tradycyjnej metody analizy składni, która jest podobna do metody Java, dostępna jest również metoda TryParse. Nie jestem dobry w składni Java (parametry wyjściowe?), Dlatego proszę traktować poniższe elementy jako pseudo-kod. Powinno to jednak wyjaśnić tę koncepcję.
boolean parseInteger(String s, out int number){try{
number =Integer.parseInt(myString);returntrue;}catch(NumberFormatException e){returnfalse;}}
Stosowanie:
int num;if(parseInteger("23", out num)){// Do something with num.}
tak, nie ma żadnych „parametrów wyjściowych” w Javie, a ponieważ opakowanie Integer jest niezmienne (dlatego nie może być użyte jako prawidłowe odwołanie do przechowywania danych wyjściowych), rozsądną opcją idiomatyczną byłoby zwrócenie obiektu Integer, który mógłby być zerowy, gdyby parsować nie powiodło się Opcją brzydszą może być przekazanie int [1] jako parametru wyjściowego.
fortran
Tak, pamiętam dyskusję o tym, dlaczego Java nie ma parametrów wyjściowych. ale zwracanie liczby całkowitej (w razie potrzeby zerowej) również byłoby w porządku, chociaż nie wiem o wydajności Javy w zakresie boksowania / rozpakowywania.
OregonGhost,
4
Lubię C # tak samo jak następny facet, ale nie ma sensu dodawać fragmentu kodu .NET C # dla pytania Java, gdy funkcje nie istnieją w Javie
Shane
Powoduje to powstanie problemu z sonarem, jeśli nie zarejestrujesz wyjątku
jmhostalet
2
Parsuj (tj. Za pomocą Integer#parseInt) i po prostu złap wyjątek. =)
Aby wyjaśnić: funkcja parseInt sprawdza, czy może parsować liczbę w każdym przypadku (oczywiście), a jeśli i tak chcesz ją przeanalizować, nie będziesz miał żadnego wpływu na wydajność poprzez wykonanie parsowania.
Jeśli nie chcesz go analizować (lub analizować bardzo, bardzo rzadko), możesz oczywiście zrobić to inaczej.
Zilustrowałem niektóre warunki sprawdzania liczb i miejsc po przecinku bez użycia interfejsu API,
Sprawdź Fix Długość 1 cyfra
Character.isDigit(char)
Sprawdź numer stałej długości (zakładając, że długość wynosi 6)
String number ="132452";if(number.matches("([0-9]{6})"))System.out.println("6 digits number identified");
Sprawdź liczbę różnych długości między (Załóżmy, że długość 4 do 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");
Sprawdź liczbę dziesiętną o zmiennej długości między (Załóżmy, że długość od 4 do 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");
Opierając się na innych odpowiedziach, napisałem własną i nie używa wzorców ani parsowania ze sprawdzaniem wyjątków.
Sprawdza maksymalnie jeden znak minus i sprawdza maksymalnie jeden przecinek dziesiętny.
Oto kilka przykładów i ich wyników:
„1”, „-1”, „-1.5” i „-1.556” zwracają wartość true
„1..5”, „1A.5”, „1.5D”, „-” i „--1” zwracają wartość false
Uwaga: W razie potrzeby możesz zmodyfikować ten parametr, aby zaakceptować parametr Locale i przekazać go do wywołań DecimalFormatSymbols.getInstance () w celu użycia określonego ustawienia regionalnego zamiast bieżącego.
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;}
Oto dwie metody, które mogą działać. (Bez użycia wyjątków). Uwaga: Java jest domyślnie wartością przekazywaną, a wartością ciągu jest adres danych obiektowych ciągu. Więc kiedy to robisz
stringNumber = stringNumber.replaceAll(" ","");
Zmieniłeś wartość wejściową, tak aby nie miała spacji. Możesz usunąć tę linię, jeśli chcesz.
Oto inna metoda na wypadek, gdybyś chciał zezwolić na liczbę zmiennoprzecinkową. Ta metoda rzekomo pozwala na przekazanie liczb w formularzu 1,123,123,123,123,123.123 właśnie ją stworzyłem i myślę, że wymaga dalszych testów, aby upewnić się, że działa.
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;}
Och, dobre pytanie. Myślę, że ten działa tylko na liczbach całkowitych normalnego typu. Metoda została początkowo stworzona do filtrowania wejściowych numerów telefonów i zliczania numerów.
Integer.parseInt()
nie będą w stanie przeanalizować numerów telefonów komórkowychNumberFormatException
.Odpowiedzi:
Z Apache Commons Lang 3.5 i nowszym:
NumberUtils.isCreatable
lubStringUtils.isNumeric
.Z Apache Commons Lang 3.4 i niższymi:
NumberUtils.isNumber
lubStringUtils.isNumeric
.Możesz także użyć,
StringUtils.isNumericSpace
które zwracatrue
puste ciągi i ignoruje wewnętrzne spacje w ciągu. Innym sposobem jest użycie,NumberUtils.isParsable
które zasadniczo sprawdza, czy liczba jest możliwa do parsowania zgodnie z Javą. (Połączone javadocs zawierają szczegółowe przykłady dla każdej metody.)źródło
StringUtils.isNumeric()
prawdopodobnie nie byłoby to właściwe tutaj, ponieważ sprawdza tylko, czy ciąg znaków jest ciągiem cyfr. Byłoby dobrze dla większości liczb całkowitych, ale nie dla liczb z ułamkami dziesiętnymi, separatorów grup itp.StringUtils
nie obsługuje znaków wiodących, ale powinieneś sprawdzićNumberUtils.isCreatable
, poprawnie obsługuje negatywy.Zasadniczo odbywa się to za pomocą prostej funkcji zdefiniowanej przez użytkownika (tj. „Włóż własną funkcję„ isNumeric ”).
Coś jak:
Jeśli jednak często wywołujesz tę funkcję i oczekujesz, że wiele kontroli zakończy się niepowodzeniem z powodu braku bycia liczbą, to działanie tego mechanizmu nie będzie świetne, ponieważ polegasz na wyjątkach zgłaszanych dla każdej awarii, co jest dość kosztowną operacją.
Alternatywnym podejściem może być użycie wyrażenia regularnego w celu sprawdzenia ważności bycia liczbą:
Uważaj jednak na powyższy mechanizm RegEx, ponieważ zawiedzie, jeśli używasz cyfr spoza arabskiego (tj. Cyfr od 0 do 9). Wynika to z faktu, że część „\ d” RegEx będzie pasować tylko do [0-9] i faktycznie nie jest międzynarodowo świadoma liczbowo. (Podziękowania dla OregonGhost za zwrócenie na to uwagi!)
Lub jeszcze inną alternatywą jest użycie wbudowanego obiektu Java java.text.NumberFormat, aby sprawdzić, czy po analizie ciągu pozycja parsera znajduje się na końcu ciągu. Jeśli tak, możemy założyć, że cały ciąg jest liczbowy:
źródło
.
w wyrażeniu regularnym będzie pasować dowolny znak, a nie tylko separator dziesiętny.jeśli używasz Androida, powinieneś użyć:
dokumentacja znajduje się tutaj
zachowaj prostotę . przeważnie każdy może „przeprogramować” (to samo).
źródło
.
,-
Wyrażenia lambda Java 8.
źródło
Jak wspomniał @CraigTP w swojej doskonałej odpowiedzi, mam podobne obawy dotyczące wydajności przy użyciu wyjątków w celu sprawdzenia, czy łańcuch jest liczbowy, czy nie. W rezultacie dzielę ciąg i używam
java.lang.Character.isDigit()
.Według Javadoc ,
Character.isDigit(char)
poprawnie rozpoznaje niełacińskie cyfr. Pod względem wydajności myślę, że prosta liczba N porównań, w których N jest liczbą znaków w łańcuchu, byłaby bardziej wydajna obliczeniowo niż dopasowanie wyrażenia regularnego.AKTUALIZACJA: Jak zauważył Jean-François Corbett w komentarzu, powyższy kod sprawdziłby tylko liczby całkowite dodatnie, co obejmuje większość mojego przypadku użycia. Poniżej znajduje się zaktualizowany kod, który poprawnie sprawdza poprawność liczb dziesiętnych zgodnie z domyślnymi ustawieniami narodowymi używanymi w systemie, przy założeniu, że separator dziesiętny występuje tylko raz w ciągu.
źródło
toCharArray()
spowoduje utworzenie kopii tablicy w obiekcie String, ponieważ ciągi są niezmienne. Prawdopodobnie szybciej użyćcharAt(int index)
metody bezpośrednio na obiekcie String.StringIndexOutOfBoundsException
kiedy przeszedł ciąg o długości 0. Może być zamocowaneif(str.length() == 0) return false;
Biblioteka Guava Google zapewnia miły metody pomocnika, aby to zrobić:
Ints.tryParse
. Używasz go w ten sposób,Integer.parseInt
ale zwraca onnull
zamiast rzucać wyjątek, jeśli ciąg nie parsuje prawidłowej liczby całkowitej. Zauważ, że zwraca Integer, a nie int, więc musisz przekonwertować / autobox z powrotem na int.Przykład:
Jednak od obecnego wydania - Guava r11 - nadal jest oznaczony @Beta.
Nie porównałem tego. Patrząc na kod źródłowy, pojawia się pewien narzut związany z dużą ilością sprawdzania poprawności, ale w końcu używają
Character.digit(string.charAt(idx))
podobnej, ale nieco innej niż odpowiedź z @Ibrahim powyżej. W ich implementacji nie ma wyjątku obsługa kosztów ogólnych pod przykryciem.źródło
Nie używaj wyjątków do sprawdzania poprawności swoich wartości. Zamiast tego użyj Util libs jak apache NumberUtils:
Edytuj :
Zauważ, że jeśli łańcuch zaczyna się od 0, NumberUtils zinterpretuje twoją wartość jako szesnastkową.
źródło
Number.isNumber()
.Number.isNumber()
była obecna od pierwszej wersji odpowiedzi, datowanej na 24 września 12 o 17:01.Dlaczego wszyscy naciskają na rozwiązania wyjątkowe / wyrażenia regularne?
Chociaż rozumiem, że większość ludzi nie ma nic przeciwko używaniu try / catch, jeśli chcesz to robić często ... może to być bardzo obciążające.
To, co zrobiłem tutaj, to wzięcie wyrażenia regularnego, metod parseNumber () i metody przeszukiwania tablicy, aby sprawdzić, która z nich była najbardziej wydajna. Tym razem spojrzałem tylko na liczby całkowite.
Wyniki, które uzyskałem, były następujące:
Oświadczenie: Nie twierdzę, że te metody są w 100% zoptymalizowane, służą jedynie do demonstracji danych
Wyjątki wygrane wtedy i tylko wtedy, gdy liczba ma 4 znaki lub mniej, a każdy ciąg jest zawsze liczbą ... w takim przypadku, po co w ogóle mieć czek?
Krótko mówiąc, jest to bardzo bolesne, jeśli często próbujesz złapać nieprawidłowe liczby za pomocą try / catch, co ma sens. Ważną zasadą, której zawsze przestrzegam jest NIGDY nie używaj try / catch do przebiegu programu . To jest przykład dlaczego.
Co ciekawe, prosty jeśli char <0 || > 9 było niezwykle łatwe do napisania, łatwe do zapamiętania (i powinno działać w wielu językach) i wygrywa prawie wszystkie scenariusze testowe.
Jedynym minusem jest to, że zgaduję, że Integer.parseInt () może obsługiwać liczby inne niż ASCII, podczas gdy metoda wyszukiwania tablicowego nie.
Dla tych, którzy zastanawiają się, dlaczego powiedziałem, że łatwo jest zapamiętać tablicę znaków, jeśli wiesz, że nie ma żadnych negatywnych znaków, możesz łatwo uciec od czegoś skondensowanego:
Wreszcie, jako ostatnia uwaga, byłem ciekawy operatora przypisania w przyjętym przykładzie z wszystkimi głosami. Dodanie w przypisaniu
jest nie tylko bezużyteczny, ponieważ nawet nie używasz tej wartości, ale marnuje czas przetwarzania i wydłuża czas działania o kilka nanosekund (co doprowadziło do wzrostu testów o 100-200 ms). Nie rozumiem, dlaczego ktoś miałby to zrobić, ponieważ w rzeczywistości jest to dodatkowa praca w celu zmniejszenia wydajności.
Można by pomyśleć, że zostałby zoptymalizowany ... chociaż może powinienem sprawdzić kod bajtowy i zobaczyć, co robi kompilator. To nie tłumaczy, dlaczego zawsze wydawało mi się, że jest dłuższe, jeśli jest w jakiś sposób zoptymalizowane ... dlatego zastanawiam się, co się dzieje. Uwaga: przez dłuższy czas mam na myśli uruchomienie testu dla iteracji 10000000, a wielokrotne uruchomienie tego programu (10x +) zawsze pokazało, że jest wolniejszy.
EDYCJA: Zaktualizowano test dla Character.isDigit ()
źródło
Wyrażenie regularne CraigTP (pokazane powyżej) powoduje pewne fałszywe alarmy. Np. „23y4” będzie liczone jako liczba, ponieważ „.” dopasowuje dowolny znak inny niż przecinek dziesiętny.
Odrzuci także dowolną liczbę z wiodącym „+”
Alternatywą, która pozwala uniknąć tych dwóch drobnych problemów, jest
źródło
true
pojedynczy plus"+"
lub minus"-"
, afalse
dla"0."
"0."
jest ważnyDouble.parseDouble()
i jest prawidłowym literałem zgodnie z JLS ( §3.10.2 )!matches("-?\\d+([.]\\d+)?")
Możemy spróbować zastąpić wszystkie liczby z podanego ciągu ciągiem („”), tj. Spacją, a jeśli po tym czasie długość łańcucha wyniesie zero, możemy powiedzieć, że podany ciąg zawiera tylko liczby. [Jeśli uznasz, że ta odpowiedź była pomocna, zastanów się nad jej głosowaniem] Przykład:
źródło
""
jest wiele, ale"3.14"
i"-1"
nie są?Możesz użyć
NumberFormat#parse
:źródło
value
.Jeśli używasz Java do tworzenia aplikacji na Androida, możesz użyć funkcji TextUtils.isDigitsOnly .
źródło
Oto moja odpowiedź na problem.
Łapacz wszystkim metoda wygoda, które można wykorzystać do analizowania dowolny ciąg z dowolnym typem parsera:
isParsable(Object parser, String str)
. Analizator składni może być aClass
lub anobject
. Umożliwi to również użycie napisanych przez Ciebie niestandardowych parserów i powinno działać na zawsze, np .:Oto mój kod wraz z opisami metod.
źródło
Aby dopasować tylko dodatnie liczby całkowite dziesięciu, które zawierają tylko cyfry ASCII, użyj:
źródło
Skuteczne podejście pozwalające uniknąć prób połowu i obsługi liczb ujemnych i notacji naukowej.
źródło
Oto moja klasa do sprawdzania, czy łańcuch jest liczbowy. Naprawia również ciągi liczbowe:
Funkcje:
Proszę bardzo...
źródło
Oto kolejny przykład ulepszonego dopasowania wyrażenia regularnego „CraigTP” z większą liczbą sprawdzeń poprawności.
źródło
Wyjątki są drogie, ale w tym przypadku RegEx trwa znacznie dłużej. Poniższy kod pokazuje prosty test dwóch funkcji - jednej z wyjątkami i drugiej z wyrażeniem regularnym. Na moim komputerze wersja RegEx jest 10 razy wolniejsza niż wyjątek.
źródło
// sprawdź poniższy kod
źródło
źródło
To prosty przykład tego sprawdzenia:
źródło
Możesz użyć obiektu java.util.Scanner.
źródło
Zmodyfikowałem rozwiązanie CraigTP, aby akceptować notację naukową oraz kropkę i przecinek jako separatory dziesiętne
przykład
źródło
Dlatego podoba mi się podejście Try * w .NET. Oprócz tradycyjnej metody analizy składni, która jest podobna do metody Java, dostępna jest również metoda TryParse. Nie jestem dobry w składni Java (parametry wyjściowe?), Dlatego proszę traktować poniższe elementy jako pseudo-kod. Powinno to jednak wyjaśnić tę koncepcję.
Stosowanie:
źródło
Parsuj (tj. Za pomocą
Integer#parseInt
) i po prostu złap wyjątek. =)Aby wyjaśnić: funkcja parseInt sprawdza, czy może parsować liczbę w każdym przypadku (oczywiście), a jeśli i tak chcesz ją przeanalizować, nie będziesz miał żadnego wpływu na wydajność poprzez wykonanie parsowania.
Jeśli nie chcesz go analizować (lub analizować bardzo, bardzo rzadko), możesz oczywiście zrobić to inaczej.
źródło
Możesz użyć NumberUtils.isCreatable () z Apache Commons Lang .
Ponieważ NumberUtils.isNumber będzie przestarzałe w 4.0, więc użyj NumberUtils.isCreatable ().
źródło
Java 8 Stream, wyrażenie lambda, interfejs funkcjonalny
Wszystkie obsługiwane sprawy ( ciąg pusty, ciąg pusty itp. )
źródło
Zilustrowałem niektóre warunki sprawdzania liczb i miejsc po przecinku bez użycia interfejsu API,
Sprawdź Fix Długość 1 cyfra
Sprawdź numer stałej długości (zakładając, że długość wynosi 6)
Sprawdź liczbę różnych długości między (Załóżmy, że długość 4 do 6)
Sprawdź liczbę dziesiętną o zmiennej długości między (Załóżmy, że długość od 4 do 7)
Mam nadzieję, że pomoże to komuś.
źródło
Opierając się na innych odpowiedziach, napisałem własną i nie używa wzorców ani parsowania ze sprawdzaniem wyjątków.
Sprawdza maksymalnie jeden znak minus i sprawdza maksymalnie jeden przecinek dziesiętny.
Oto kilka przykładów i ich wyników:
„1”, „-1”, „-1.5” i „-1.556” zwracają wartość true
„1..5”, „1A.5”, „1.5D”, „-” i „--1” zwracają wartość false
Uwaga: W razie potrzeby możesz zmodyfikować ten parametr, aby zaakceptować parametr Locale i przekazać go do wywołań DecimalFormatSymbols.getInstance () w celu użycia określonego ustawienia regionalnego zamiast bieżącego.
źródło
Oto dwie metody, które mogą działać. (Bez użycia wyjątków). Uwaga: Java jest domyślnie wartością przekazywaną, a wartością ciągu jest adres danych obiektowych ciągu. Więc kiedy to robisz
Zmieniłeś wartość wejściową, tak aby nie miała spacji. Możesz usunąć tę linię, jeśli chcesz.
Oto inna metoda na wypadek, gdybyś chciał zezwolić na liczbę zmiennoprzecinkową. Ta metoda rzekomo pozwala na przekazanie liczb w formularzu 1,123,123,123,123,123.123 właśnie ją stworzyłem i myślę, że wymaga dalszych testów, aby upewnić się, że działa.
źródło