문자열을 구문 분석하기 전에 숫자인지 어떻게 확인합니까?
Integer.parseInt()
과)의 휴대 전화 번호를 구문 분석하지 못합니다 NumberFormatException
.
문자열을 구문 분석하기 전에 숫자인지 어떻게 확인합니까?
Integer.parseInt()
과)의 휴대 전화 번호를 구문 분석하지 못합니다 NumberFormatException
.
답변:
와 아파치 코 몬즈 랭 3.5 이상 : NumberUtils.isCreatable
나 StringUtils.isNumeric
.
와 아파치 코 몬즈 랭 3.4 이하 : NumberUtils.isNumber
나 StringUtils.isNumeric
.
빈 문자열에 대한 StringUtils.isNumericSpace
반환 값 true
을 사용 하고 문자열의 내부 공간을 무시할 수도 있습니다 . 또 다른 방법은 NumberUtils.isParsable
기본적으로 Java에 따라 파싱 가능한 수를 확인하는 사용 하는 것입니다. 링크 된 javadoc에는 각 메소드에 대한 자세한 예제가 포함되어 있습니다.
StringUtils.isNumeric()
문자열이 일련의 숫자인지 확인하기 때문에 여기에 적합하지 않을 것입니다. 대부분의 int에 대한 미세하지만 그렇게 등 소수, 그룹 단락 문자와 숫자가 될 것입니다
StringUtils
선행 기호는 지원하지 않지만 확인해야 NumberUtils.isCreatable
합니다. 음수를 올바르게 지원합니다.
이것은 일반적으로 간단한 사용자 정의 함수 (예 : Roll-your-own "isNumeric"함수)로 수행됩니다.
다음과 같은 것 :
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e){
return false;
}
}
그러나이 함수를 많이 호출하고 숫자가 아니기 때문에 많은 검사가 실패 할 것으로 예상하면이 메커니즘의 성능은 좋지 않습니다. 각 실패마다 예외가 발생하기 때문입니다. 상당히 비싼 작업입니다.
다른 방법은 정규식을 사용하여 숫자의 유효성을 검사하는 것입니다.
public static boolean isNumeric(String str) {
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
그러나 아랍어 이외의 숫자 (예 : 0에서 9 이외의 숫자)를 사용하면 위의 RegEx 메커니즘에주의해야합니다. 이는 RegEx의 "\ d"부분이 [0-9]에만 일치하고 효과적으로 국제적으로 숫자를 인식하지 못하기 때문입니다. (OregonGhost에게 이것을 지적 해 주셔서 감사합니다!)
또는 다른 대안은 Java의 내장 java.text.NumberFormat 객체를 사용하여 문자열을 구문 분석 한 후 구문 분석기 위치가 문자열의 끝에 있는지 확인하는 것입니다. 그렇다면 전체 문자열이 숫자라고 가정 할 수 있습니다.
public static boolean isNumeric(String str) {
NumberFormat formatter = NumberFormat.getInstance();
ParsePosition pos = new ParsePosition(0);
formatter.parse(str, pos);
return str.length() == pos.getIndex();
}
.
하여 정규식에 어떤 문자 만이 아니라 소수 구분 문자와 일치합니다.
당신이 안드로이드에 있다면, 당신은 사용해야합니다 :
android.text.TextUtils.isDigitsOnly(CharSequence str)
간단하게 유지하십시오 . 대부분의 사람들은 "다시 프로그래밍"할 수 있습니다 (같은 것).
.
,-
Java 8 람다 식.
String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );
@CraigTP가 그의 탁월한 답변에서 언급했듯이 예외를 사용하여 문자열이 숫자인지 여부를 테스트하는 것과 비슷한 성능 문제가 있습니다. 그래서 문자열을 나누고을 사용 java.lang.Character.isDigit()
합니다.
public static boolean isNumeric(String str)
{
for (char c : str.toCharArray())
{
if (!Character.isDigit(c)) return false;
}
return true;
}
에 따르면 Javadoc을 , Character.isDigit(char)
의지가 제대로 라틴어가 아닌 숫자를 인식합니다. 성능 측면에서, N이 문자열의 문자 수인 간단한 N 수의 비교는 정규식 일치를 수행하는 것보다 계산적으로 효율적이라고 생각합니다.
업데이트 : 의견에서 Jean-François Corbett이 지적한 것처럼 위의 코드는 양의 정수 만 유효성을 검사하므로 대부분의 유스 케이스를 포괄합니다. 다음은 시스템에서 사용되는 기본 로케일에 따라 소수를 올바르게 유효성 검증하는 업데이트 된 코드이며 소수 구분 기호는 문자열에서 한 번만 발생한다는 가정입니다.
public static boolean isStringNumeric( String str )
{
DecimalFormatSymbols currentLocaleSymbols = DecimalFormatSymbols.getInstance();
char localeMinusSign = currentLocaleSymbols.getMinusSign();
if ( !Character.isDigit( str.charAt( 0 ) ) && str.charAt( 0 ) != localeMinusSign ) return false;
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;
}
return false;
}
}
return true;
}
toCharArray()
문자열은 변경할 수 없으므로 호출 하면 String 객체에 배열의 복사본이 만들어집니다. 아마도 charAt(int index)
String 객체 에서 메소드를 직접 사용하는 것이 더 빠를 것 입니다.
StringIndexOutOfBoundsException
길이가 0 인 문자열을 전달하면 생성 됩니다. 다음과 같이 수정 가능if(str.length() == 0) return false;
Google의 구아바 라이브러리는 다음과 같은 유용한 도우미 방법을 제공합니다 Ints.tryParse
. 당신은 같이 사용할 수 Integer.parseInt
있지만 반환 null
이 아닌 문자열이 유효한 정수로 구문 분석하지 않는 경우 예외를 throw합니다. int가 아닌 Integer를 반환하므로 int로 다시 변환 / 오토 박스해야합니다.
예:
String s1 = "22";
String s2 = "22.2";
Integer oInt1 = Ints.tryParse(s1);
Integer oInt2 = Ints.tryParse(s2);
int i1 = -1;
if (oInt1 != null) {
i1 = oInt1.intValue();
}
int i2 = -1;
if (oInt2 != null) {
i2 = oInt2.intValue();
}
System.out.println(i1); // prints 22
System.out.println(i2); // prints -1
그러나 현재 릴리스 인 Guava r11에서는 여전히 @Beta로 표시되어 있습니다.
나는 그것을 벤치마킹하지 않았습니다. 소스 코드를 보면 많은 온 전성 검사로 인한 오버 헤드가 있지만 결국 Character.digit(string.charAt(idx))
@Ibrahim의 대답과 비슷하지만 약간 다릅니다. 구현시 커버 아래에서 예외 처리 오버 헤드가 없습니다.
값을 확인하기 위해 예외를 사용하지 마십시오. 아파치 NumberUtils 대신 Util 라이브러리를 사용하십시오 :
NumberUtils.isNumber(myStringValue);
편집 :
문자열이 0으로 시작하면 NumberUtils는 값을 16 진수로 해석합니다.
NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false
Number.isNumber()
.
Number.isNumber()
9 월 24 일 12시 17 분 1 초의 답변 의 첫 번째 버전에서 나온 것을 보여줍니다 .
왜 모두가 예외 / 정규 솔루션을 추진하고 있습니까?
try / catch를 사용하면 대부분의 사람들이 훌륭하다는 것을 알 수 있지만 자주하고 싶다면 너무 과세 될 수 있습니다.
내가 여기서 한 일은 정규식, parseNumber () 메소드 및 배열 검색 메소드를 사용하여 가장 효율적인 것을 확인하는 것입니다. 이번에는 정수만 보았습니다.
public static boolean isNumericRegex(String str) {
if (str == null)
return false;
return str.matches("-?\\d+");
}
public static boolean isNumericArray(String str) {
if (str == null)
return false;
char[] data = str.toCharArray();
if (data.length <= 0)
return false;
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.
return false;
}
return true;
}
public static boolean isNumericException(String str) {
if (str == null)
return false;
try {
/* int i = */ Integer.parseInt(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
내가 얻은 속도의 결과는 다음과 같습니다.
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 sign
Array 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]
With null:
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를 사용하지 않는 것 입니다. 이것이 왜 예입니다.
흥미롭게도 간단한 경우 char <0 || > 9는 작성이 매우 간단하고 기억하기 쉬우 며 (다국어로 작동해야 함) 거의 모든 테스트 시나리오에서 승리했습니다.
유일한 단점은 Integer.parseInt ()가 ASCII가 아닌 숫자를 처리 할 수 있다고 생각하지만 배열 검색 방법은 그렇지 않습니다.
내가 왜 문자 배열 1을 기억하는 것이 쉬운 지 궁금해하는 사람들을 위해, 음수 부호가 없다는 것을 알고 있다면 다음과 같이 요약 된 것을 쉽게 벗어날 수 있습니다.
public static boolean isNumericArray(String str) {
if (str == null)
return false;
for (char c : str.toCharArray())
if (c < '0' || c > '9')
return false;
return true;
마지막으로 마지막으로, 나는 모든 투표권을 가진 수락 된 예제에서 어설 션 연산자에 대해 궁금했습니다. 할당에 추가
double d = Double.parseDouble(...)
값을 사용하지 않기 때문에 쓸모가 없을뿐만 아니라 처리 시간을 낭비하고 런타임을 몇 나노초까지 늘 렸습니다 (테스트에서 100-200ms 증가). 실제로 성능을 낮추기위한 추가 작업이므로 다른 사람이 왜 그렇게하는지 알 수 없습니다.
당신은 그것이 최적화 될 것이라고 생각할 것입니다 ...하지만 아마도 바이트 코드를 확인하고 컴파일러가 무엇을하고 있는지 확인해야합니다. 그것은 어떻게 든 최적화되어 있지만 항상 나에게 더 길어진 이유를 설명하지는 않습니다 ... 그래서 나는 무슨 일이 일어나고 있는지 궁금합니다. 참고로 더 길어지면 10000000 반복 테스트를 실행하고 해당 프로그램을 여러 번 실행하면 (10x +) 항상 느려진 것으로 나타났습니다.
편집 : Character.isDigit ()에 대한 테스트가 업데이트되었습니다.
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(.\\d+)?");
}
CraigTP의 정규 표현식 (위에 표시됨)은 약간의 오탐 (false positive)을 생성합니다. 예를 들어, "23y4"는 '.'때문에 숫자로 계산됩니다. 소수점이 아닌 모든 문자와 일치합니다.
또한 선행 '+'가있는 숫자는 거부합니다.
이 두 가지 사소한 문제를 피하는 대안은
public static boolean isNumeric(String str)
{
return str.matches("[+-]?\\d*(\\.\\d+)?");
}
true
하나의 플러스 "+"
또는 마이너스 "-"
, 그리고 false
위한"0."
matches("-?\\d+([.]\\d+)?")
주어진 문자열의 모든 숫자를 빈 공간 ( "")으로 바꾸려고 시도 할 수 있습니다. 즉, 빈 공간이 0 인 경우 주어진 문자열에 숫자 만 포함되어 있다고 말할 수 있습니다. [이 답변이 도움이 되었으면 투표를 고려하십시오] 예 :
boolean isNumber(String str){
if(str.length() == 0)
return false; //To check if string is empty
if(str.charAt(0) == '-')
str = str.replaceFirst("-","");// for handling -ve numbers
System.out.println(str);
str = str.replaceFirst("\\.",""); //to check if it contains more than one decimal points
if(str.length() == 0)
return false; // to check if it is empty string after removing -ve sign and decimal point
System.out.println(str);
return str.replaceAll("[0-9]","").length() == 0;
}
""
숫자에 불과하다 "3.14"
하고 "-1"
있지?
당신은 사용할 수 있습니다 NumberFormat#parse
:
try
{
NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
// Not a number.
}
value
.
java를 사용하여 Android 앱을 개발하는 경우 TextUtils.isDigitsOnly 함수를 사용할 수 있습니다.
여기에 문제에 대한 대답이 있습니다.
모든 유형의 구문 분석기로 문자열을 구문 분석하는 데 사용할 수있는 모든 편리한 메소드를 포착하십시오 isParsable(Object parser, String str)
. 파서는 a Class
또는 a 일 수 있습니다 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
*/
public static boolean isParsable(Object parser, String str) {
Class theClass = (parser instanceof Class? (Class)parser: parser.getClass());
boolean staticOnly = (parser == theClass), foundAtLeastOne = false;
Method[] methods = theClass.getMethods();
// Loop over methods
for (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);
return true; // 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 method
continue; // Look for other parse methods
}
}
}
// No more accessible parse method could be found.
if(foundAtLeastOne) return false;
else throw new RuntimeException(new NoSuchMethodException());
}
/**
* 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
*/
public static boolean willParse(Object parser, String str) {
try {
return isParsable(parser, str);
} catch(Throwable exception) {
return false;
}
}
다음은 문자열이 숫자인지 확인하는 클래스입니다. 또한 숫자 문자열을 수정합니다.
여기 있습니다 ...
public class NumUtils {
/**
* Transforms a string to an integer. If no numerical chars returns a String "0".
*
* @param str
* @return retStr
*/
static String 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
*/
static String makeToDouble(String str) {
Boolean dotWasFound = false;
String orgStr = str;
String retStr;
int firstDotPos = 0;
Boolean negative = false;
//check if str is null
if(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 dots
for (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 begining
double 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;
}
static boolean isNumeric(String str) {
try {
double d = Double.parseDouble(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
}
정규식 일치
다음은 더 많은 검증과 일치하는 업그레이드 된 "CraigTP"정규식의 또 다른 예입니다.
public static boolean isNumeric(String str)
{
return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
정규식 테스트
1 -- **VALID**
1. -- INVALID
1.. -- INVALID
1.1 -- **VALID**
1.1.1 -- INVALID
-1 -- **VALID**
--1 -- INVALID
-1. -- INVALID
-1.1 -- **VALID**
-1.1.1 -- INVALID
예외는 비싸지 만이 경우 RegEx는 훨씬 오래 걸립니다. 아래 코드는 예외를 사용하는 것과 정규식을 사용하는 두 가지 함수에 대한 간단한 테스트를 보여줍니다. 내 컴퓨터에서 RegEx 버전이 예외보다 10 배 느립니다.
import java.util.Date;
public class IsNumeric {
public static boolean isNumericOne(String s) {
return s.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
public static boolean isNumericTwo(String s) {
try {
Double.parseDouble(s);
return true;
} catch (Exception e) {
return false;
}
}
public static void main(String [] args) {
String test = "12345.F";
long before = new Date().getTime();
for(int x=0;x<1000000;++x) {
//isNumericTwo(test);
isNumericOne(test);
}
long after = new Date().getTime();
System.out.println(after-before);
}
}
// only int
public static boolean isNumber(int num)
{
return (num >= 48 && c <= 57); // 0 - 9
}
// is type of number including . - e E
public static boolean 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
public static boolean 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;
}
public static boolean isNumeric(String s)
{
try
{
Double.parseDouble(s);
return true;
}
catch (Exception e)
{
return false;
}
}
이것은이 검사에 대한 간단한 예입니다.
public static boolean 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 = new RegExp("^-?\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
.NET의 Try * 접근 방식이 마음에 드는 이유입니다. Java와 유사한 전통적인 Parse 메소드 외에도 TryParse 메소드도 있습니다. Java 구문 (매개 변수가 아님)이 좋지 않으므로 다음을 일종의 의사 코드로 취급하십시오. 그래도 개념을 분명히해야합니다.
boolean parseInteger(String s, out int number)
{
try {
number = Integer.parseInt(myString);
return true;
} catch(NumberFormatException e) {
return false;
}
}
용법:
int num;
if (parseInteger("23", out num)) {
// Do something with num.
}
구문 분석하고 (예 :로 Integer#parseInt
) 예외를 포착하십시오. =)
명확히하기 위해 : parseInt 함수는 어떤 경우에도 숫자를 구문 분석 할 수 있는지 확인하고 (어쩌면) 구문 분석하려는 경우 실제로 구문 분석을 수행하여 성능 저하를 일으키지 않습니다.
당신이 그것을 파싱하고 싶지 않거나 (매우 드물게 파싱하고 싶다면) 물론 다르게 할 수도 있습니다.
Apache Commons Lang의 NumberUtils.isCreatable ()을 사용할 수 있습니다 .
NumberUtils.isNumber는 4.0에서 더 이상 사용되지 않으므로 NumberUtils.isCreatable ()을 대신 사용하십시오.
Java 8 스트림, 람다 식, 기능 인터페이스
모든 경우 처리 ( string null, string empty 등 )
String someString = null; // something="", something="123abc", something="123123"
boolean isNumeric = Stream.of(someString)
.filter(s -> s != null && !s.isEmpty())
.filter(Pattern.compile("\\D").asPredicate().negate())
.mapToLong(Long::valueOf)
.boxed()
.findAny()
.isPresent();
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 <= m
String 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 길이 가정) 사이의 가변 길이 10 진수 확인
// It will not count the '.' (Period) in length
String 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", "-1", "-1.5"및 "-1.556"이 true를 반환
"1..5", "1A.5", "1.5D", "-"및 "--1"은 false를 반환합니다.
참고 : 필요한 경우 Locale 매개 변수를 승인하고이를 DecimalFormatSymbols.getInstance () 호출로 전달하여 현재 로케일 대신 특정 로케일을 사용할 수 있습니다.
public static boolean isNumeric(final String input) {
//Check for null or blank string
if(input == null || input.isBlank()) return false;
//Retrieve the minus sign and decimal separator characters from the current Locale
final var localeMinusSign = DecimalFormatSymbols.getInstance().getMinusSign();
final var localeDecimalSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
//Check if first character is a minus sign
final var isNegative = input.charAt(0) == localeMinusSign;
//Check if string is not just a minus sign
if (isNegative && input.length() == 1) return false;
var isDecimalSeparatorFound = false;
//If the string has a minus sign ignore the first character
final 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 separator
for (var i = startCharIndex; i < input.length(); i++) {
if(!Character.isDigit(input.charAt(i))) {
if(input.charAt(i) == localeDecimalSeparator && !isDecimalSeparatorFound) {
isDecimalSeparatorFound = true;
} else return false;
}
}
return true;
}
작동 할 수있는 두 가지 방법이 있습니다. (예외를 사용하지 않고). 참고 : Java는 기본적으로 값으로 전달되며 문자열 값은 문자열 객체 데이터의 주소입니다. 그래서, 당신이 할 때
stringNumber = stringNumber.replaceAll(" ", "");
공백이 없도록 입력 값을 변경했습니다. 원하는 경우 해당 줄을 제거 할 수 있습니다.
private boolean isValidStringNumber(String stringNumber)
{
if(stringNumber.isEmpty())
{
return false;
}
stringNumber = stringNumber.replaceAll(" ", "");
char [] charNumber = stringNumber.toCharArray();
for(int i =0 ; i<charNumber.length ;i++)
{
if(!Character.isDigit(charNumber[i]))
{
return false;
}
}
return true;
}
여기에 부동 소수점을 허용하려는 경우 다른 방법이 있습니다.이 방법은 양식의 숫자가 1,123,123,123,123,123.123을 통과하도록 허용합니다. 방금 만들었고 작동하는지 확인하기 위해 추가 테스트가 필요하다고 생각합니다.
private boolean isValidStringTrueNumber(String stringNumber)
{
if(stringNumber.isEmpty())
{
return false;
}
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))
{
return false;
}
if(!Character.isDigit(charNumber[i]))//Char is not a digit.
{
if(charNumber[i]==',')
{
if(decimalPointPassed)
{
return false;
}
commaFound = true;
//check that next three chars are only digits.
commaCounter +=3;
}
else if(charNumber[i]=='.')
{
decimalPointPassed = true;
countOfDecimalPoint++;
}
else
{
return false;
}
}
else //Char is a digit.
{
if ((commaCounter>=0)&&(commaFound))
{
if(!decimalPointPassed)
{
commaCounter--;
}
}
if(!commaFound)
{
countOfDigitsBeforeFirstComma++;
}
if(!decimalPointPassed)
{
countOfDigitsBeforeDecimalPoint++;
}
else
{
countOfDigitsAfterDecimalPoint++;
}
}
}
if((commaFound)&&(countOfDigitsBeforeFirstComma>3))
{
return false;
}
if(countOfDecimalPoint>1)
{
return false;
}
if((decimalPointPassed)&&((countOfDigitsBeforeDecimalPoint==0)||(countOfDigitsAfterDecimalPoint==0)))
{
return false;
}
return true;
}