Development Tip

Java에서 문자열이 숫자인지 확인하는 방법

yourdevel 2020. 9. 28. 10:15
반응형

Java에서 문자열이 숫자인지 확인하는 방법


구문 분석하기 전에 문자열이 숫자인지 어떻게 확인합니까?


아파치 코 몬즈 랭 3.5 이상 : NumberUtils.isCreatableStringUtils.isNumeric.

아파치 코 몬즈 랭 3.4 이하 : NumberUtils.isNumberStringUtils.isNumeric.

빈 문자열에 대해 StringUtils.isNumericSpace어떤 반환 true사용 하고 문자열의 내부 공백을 무시할 수도 있습니다 . 또 다른 방법은 StringUtils.isParsable기본적으로 Java에 따라 숫자를 구문 분석 할 수 있는지 확인하는 사용 입니다. (링크 된 javadocs에는 각 메소드에 대한 자세한 예제가 포함되어 있습니다.)


이 작업은 일반적으로 간단한 사용자 정의 함수 (예 : Roll-your-own "isNumeric"함수)로 수행됩니다.

다음과 같은 것 :

public static boolean isNumeric(String str) { 
  try {  
    Double.parseDouble(str);  
    return true;
  } catch(NumberFormatException e){  
    return false;  
  }  
}

그러나이 함수를 많이 호출하고 숫자가 아니기 때문에 많은 검사가 실패 할 것으로 예상하면 각 실패에 대해 throw되는 예외에 의존하기 때문에이 메커니즘의 성능이 좋지 않습니다. 상당히 비싼 작업입니다.

다른 방법은 정규식을 사용하여 숫자의 유효성을 확인하는 것입니다.

public static boolean isNumeric(String str) {
  return str.matches("-?\\d+(\\.\\d+)?");  //match a number with optional '-' and decimal.
}

위의 RegEx 메커니즘에주의하십시오. 아라비아 숫자가 아닌 숫자 (즉, 0에서 9까지가 아닌 숫자)를 사용하는 경우 실패 할 수 있습니다. 이는 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를 사용하는 경우 다음을 사용해야합니다.

android.text.TextUtils.isDigitsOnly(CharSequence str)

문서는 여기에서 찾을 수 있습니다.

간단하게 유지하십시오 . 대부분 모두가 "재 프로그래밍"할 수 있습니다 (같은 일).


@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;
}

자바 8 람다 식.

String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );

Google의 Guava 라이브러리는이를 수행 할 수있는 멋진 도우미 메서드를 제공합니다 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 libs를 사용하십시오.

NumberUtils.isNumber(myStringValue);

편집 :

문자열이 0으로 시작하면 NumberUtils는 값을 16 진수로 해석합니다.

NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false

모두가 예외 / 정규식 솔루션을 추진하는 이유는 무엇입니까?

대부분의 사람들이 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를 사용하지 않는다는 것 입니다. 이것이 그 이유의 예입니다.

흥미롭게도 간단한 if 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 증가). 실제로 성능을 낮추기위한 추가 작업이기 때문에 누군가 그렇게하는 이유를 알 수 없습니다.

당신은 그것이 최적화 될 것이라고 생각할 것입니다 ... 아마도 바이트 코드를 확인하고 컴파일러가 무엇을하는지 확인해야합니다. 그것이 어떻게 든 최적화되어 있다면 그것이 항상 나에게 더 길어진 것처럼 보이는 이유를 설명하지 못합니다 ... 그래서 무슨 일이 일어나고 있는지 궁금합니다. 참고 : 더 길다는 것은 10,000,000 회 반복 테스트를 실행하고 해당 프로그램을 여러 번 (10x +) 실행하면 항상 느려진 것으로 나타났습니다.

편집 : Character.isDigit () 테스트 업데이트


public static boolean isNumeric(String str)
{
    return str.matches("-?\\d+(.\\d+)?");
}

CraigTP의 정규 표현식 (위에 표시됨)은 일부 오탐을 생성합니다. 예 : '.'때문에 "23y4"는 숫자로 계산됩니다. 소수점이 아닌 모든 문자와 일치합니다.

또한 선행 '+'가있는 모든 숫자를 거부합니다.

이 두 가지 사소한 문제를 피하는 대안은

public static boolean isNumeric(String str)
{
    return str.matches("[+-]?\\d*(\\.\\d+)?");
}

다음을 사용할 수 있습니다 NumberFormat#parse.

try
{
     NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
    // Not a number.
}

주어진 문자열의 모든 숫자를 ( "") 즉, 공백으로 대체 할 수 있으며 그 이후에 문자열의 길이가 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;
    }

Java를 사용하여 Android 앱을 개발하는 경우 TextUtils.isDigitsOnly 함수를 사용할 수 있습니다.


문제에 대한 나의 대답은 다음과 같습니다.

모든 유형의 구문 분석기를 사용하여 문자열을 구문 분석하는 데 사용할 수있는 모든 편리한 방법 : 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 
 */
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;
    }
}

ASCII 숫자 만 포함하는 양의 10 진 정수만 일치 시키려면 다음을 사용하십시오.

public static boolean isNumeric(String maybeNumeric) {
    return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
}

try-catch를 피하고 음수와 과학적 표기법을 처리하는 효과적인 접근 방식입니다.

Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );

public static boolean isNumeric( String value ) 
{
    return value != null && PATTERN.matcher( value ).matches();
}

다음은 문자열이 숫자인지 확인하는 수업입니다. 또한 숫자 문자열을 수정합니다.

풍모:

  1. 불필요한 0을 제거합니다. [ "12.0000000"-> "12"]
  2. 불필요한 0 제거 [ "12.0580000"-> "12.058"]
  3. 숫자가 아닌 문자 제거 [ "12.00sdfsdf00"-> "12"]
  4. 음수 문자열 값 처리 [ "-12,020000"-> "-12.02"]
  5. 여러 점 제거 [ "-12.0.20.000"-> "-12.02"]
  6. 추가 라이브러리없이 표준 Java

여기 있습니다 ...

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. 음수 부호 -하나만 허용되며 시작 부분에 있어야합니다.
  2. 음수 부호 뒤에는 숫자가 있어야합니다.
  3. 소수점 하나만 .허용됩니다.
  4. 소수점 뒤에는 숫자가 있어야합니다.

정규식 테스트

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);

}

}

// 아래 코드를 확인하세요

public static boolean isDigitsOnly(CharSequence str) {
    final int len = str.length();
    for (int i = 0; i < len; i++) {
        if (!Character.isDigit(str.charAt(i))) {
            return false;
        }
    }
    return true;
}

// 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;
}

java.util.Scanner 객체를 사용할 수 있습니다.

public static boolean isNumeric(String inputData) {
      Scanner sc = new Scanner(inputData);
      return sc.hasNextInt();
    }

과학적 표기법과 점과 쉼표를 소수점 구분 기호로 모두 허용하도록 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 구문 (out parameters?)이 좋지 않으므로 다음을 일종의 의사 코드로 취급하십시오. 그래도 개념을 명확히해야합니다.

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 ()을 사용하십시오.


자바 8 스트림, 람다 표현식, 기능적 인터페이스

처리되는 모든 케이스 ( 문자열 null, 문자열 비어 있음 등 )

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 길이 가정) 사이의 가변 길이 십진수 확인

//  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;
}

참고 URL : https://stackoverflow.com/questions/1102891/how-to-check-if-a-string-is-numeric-in-java

반응형