I did it, but this approach seems to me to be wrong:
private static boolean isDigit(String s) throws NumberFormatException { try { Integer.parseInt(s); return true; } catch (NumberFormatException e) { return false; } } I did it, but this approach seems to me to be wrong:
private static boolean isDigit(String s) throws NumberFormatException { try { Integer.parseInt(s); return true; } catch (NumberFormatException e) { return false; } } I understand that the goal is to check Integer ? Then you can:
s.matches("[-+]?\\d+") // Π΄Π»Ρ ΡΠΏΠΈΡΠΊΠ° ΠΈΠ· 1 ΠΌΠ»Π½ ΡΠ΅Π»ΡΡ
ΡΠΈΡΠ΅Π» ΠΈ Π½Π΅ ΡΠΈΡΠ΅Π» // (ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ 50/50) ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΡΡΡ ΡΡΠΎΠΉ ΡΡΡΠΎΡΠΊΠΈ ΠΏΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ // Π½Π΅ ΠΎΡΠ»ΠΈΡΠ°Π΅ΡΡΡ ΠΎΡ ΠΎΠΏΠΈΡΠ°Π½Π½ΠΎΠΉ Π² Π²ΠΎΠΏΡΠΎΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ. If double , but without exponential notation, then
((-|\\+)?[0-9]+(\\.[0-9]+)?)+ such a regular fit.
Although I would not steamed and would do the same, only with Double.parseDouble(s) , but I'm not an indicator :) And I also paid attention to the name of the method - it is not very correct, because first, there is one in the Character class, and second, the meaning isNumeric() . But these are just comments from the "what I think about this."
There is a very good static method in commons-lang (the NumberUtils class) that takes into account the many features of Java numbers:
/** * <p>Checks whether the String a valid Java number.</p> * * <p>Valid numbers include hexadecimal marked with the <code>0x</code> * qualifier, scientific notation and numbers marked with a type * qualifier (eg 123L).</p> * * <p><code>Null</code> and empty String will return * <code>false</code>.</p> * * @param str the <code>String</code> to check * @return <code>true</code> if the string is a correctly formatted number */ public static boolean isNumber(String str) The method described in the question is the most correct method.
Methods that check whether a string consists only of numbers will not cope with the overflow (try the number 100000000000000000000000000000000 ). The correct pattern for an integer is :
^(-?([1-9][0-9]{0,8} |1[0-9]{9} |20[0-9]{8} |21[0-3][0-9]{7} |214[0-6][0-9]{6} |2147[0-3][0-9]{5} |21474[0-7][0-9]{4} |214748[0-2][0-9]{3} |2147483[0-5][0-9]{2} |21474836[0-3][0-9]{1} |214748364[0-7] ) |-2147483648 |0)$ and believe you donβt want to debug it or adapt it for other types.
In this case, decisions based on patterns will not take into account the locale and the allowed bit delimiters . So try to parse and catch an exception - almost the only correct solution.
int.TryParse . - VladDint 'a parsers and praying to Gosling to be consistent is very wrong. The logic for parsing an int from a string should only be in one place, and this place is Integer.parseInt . - VladDAs long as your regular expression is compiled ...
public boolean isNumber(String str) { if (str == null || str.isEmpty()) return false; for (int i = 0; i < str.length(); i++) { if (!Character.isDigit(str.charAt(i))) return false; } return true; } If you write under android , then you can use android.text.TextUtils :
boolean isDigits = TextUtils.isDidgistOnly("123"); In connection with the increased interest on this issue, I did a little research :)
The full code is available here .
The study involved classes:
CharacterDelegator() // ΠΊΠΎΠ΄ @Sergey ComplexMatcher() // ΠΊΠΎΠ΄ @VladD NumberUtilsDelegator() // ΠΌΠΎΠΉ ΠΊΠΎΠ΄ SimpleMatcher() // ΠΊΠΎΠ΄ @ivkremer (Π΄Π»Ρ ΠΏΡΠΎΡΡΡΡ
ΡΠΈΡΠ΅Π») GuavaDelegator() // ΠΊΠΎΠ΄ @Nofateβ¦ SimpleMatcherWithDot() // ΠΊΠΎΠ΄ @ivkremer (Π΄Π»Ρ ΡΠΈΡΠ΅Π» Ρ ΡΠΎΡΠΊΠΎΠΉ) SimpleParser() // ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»ΡΠ½ΡΠΉ ΠΊΠΎΠ΄ ΠΎΡ @pol GuavaComplexDelegator() // ΠΌΠΎΠ΄ΠΈΡΠΈΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ Π²Π°ΡΠΈΠ°Π½Ρ ΠΊΠΎΠ΄Π° @Nofateβ¦ Π΄Π»Ρ Float InnerSetImpl() // ΠΌΠΎΠΉ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π²Π°ΡΠΈΠ°Π½Ρ (@VladD, I apologize, I understand what your regexp is doing, but I could not get it)
Test data:
{"1", "1.1", "1.11", "1.0", "-1", "-1.0", "-1.1", "4563575687468353456", "1l", "1L", "1f", "1F", "0xCAFEBABE", "1F", "10000000000000000000000000000000000000000000000000", "1.26767E108"} There is a lot of output, so in short:
But the most interesting is the time of this code.
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
The test is constructed as follows.
We generate 2 random lists with strings (numbers). There are 4 options:
1. ΠΡΠΎΡΡΠΎ ΠΠ½ΡΡ. 2. Π§ΠΈΡΠ»Π° (Ρ 50% Π²Π΅ΡΠΎΡΡΠ½ΠΎΡΡΡΡ Π² ΡΡΡΠΈΠ½Π³Π΅ Π΅ΡΡΡ ΡΠΎΡΠΊΠ°). 3. Π§ΠΈΡΠ»Π° Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ (25% ΡΡΠΎ Π² ΡΡΡΠΎΠΊΠ΅ Π΅ΡΡΡ ΠΏΠΎΠ΄ΡΡΡΠΎΠΊΠ° "error"). 4. ΠΠ°Π±ΠΎΡ ΠΠ½ΡΠΎΠ² Π² Π½Π΅Π±ΠΎΠ»ΡΡΠΎΠΌ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅. We make a test run on 10_000 elements.
From the above calculations, you can see that NumberUtils is the fastest. Similar time of work at simple options of Guava `and simple regexp. Even adding a simple dot slows down the code considerably. I also note that the @Sergey code works very quickly, but it is designed to check strictly ints.
And there is my specific example InnerSetImpl . It is based on the assumption that we have a limited number of possible options (that is, we can and are ready to keep them in memory). Then we just put them in the HashSet and check for the presence of lines in it. Actually, this option is the fastest, but the assumption spoils a lot :)
TOTAL: if you need a simple and elegant solution, then it is best to use NumberUtils.isNumber(str) and not to bathe.
And if suddenly you have a specific task for parsing not just numbers, but numbers in Java notations, then this is the only fully working version.
(All of the above applies only to the above code. I do not exclude that it is possible to come up with (or even exist) a more correct or faster solution).
If the project already uses Google Guava, then you can take from there Ints.tryParse()
The method checks whether the string consists solely of ASCII digits and an optional sign - ( + does not work, unlike the native Integer.parse() ) and tries to match to a number. In case of failure, returns null :
Integer a = Ints.tryParse("42ΠΆ"); // null Integer b = Ints.tryParse("42"); // 42 Integer c = Ints.tryParse("+1"); // null To check double numbers
private static boolean numeralOrNot(String str) { if (str == null || str.isEmpty()) { return false; } int commaCount = 0; for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '.') { commaCount++; } if ((!Character.isDigit(str.charAt(i)) && str.charAt(i) != '.' && str.charAt(i) != '-') || commaCount > 1) { return false; } } return true; } Source: https://ru.stackoverflow.com/questions/58760/
All Articles