在解析字符串之前,如何检查它是否是一个数字?


当前回答

一个有效的方法避免尝试捕获和处理负数和科学符号。

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

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

其他回答

如果你们用下面的方法来检查:

public static boolean isNumeric(String str) {
    NumberFormat formatter = NumberFormat.getInstance();
    ParsePosition pos = new ParsePosition(0);
    formatter.parse(str, pos);
    return str.length() == pos.getIndex();
}

然后输入非常长的字符串会发生什么,比如我调用这个方法:

System.out.println(isNumeric("94328948243242352525243242524243425452342343948923"));

结果是“真”,也是一个太大的数字! 如果你使用regex来检查,同样的事情也会发生! 所以我宁愿使用“解析”方法来检查,就像这样:

public static boolean isNumeric(String str) {
    try {
        int number = Integer.parseInt(str);
        return true;
    } catch (Exception e) {
        return false;
    }
}

结果就如我所料!

这里有两种可能有效的方法。(不使用异常)。 注意:Java默认是值传递,String的值是String对象数据的地址。 所以,当你在做

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

这里是另一个方法,以防你想允许浮动 据称,这种方法允许表单中的数字通过 1123123123123123年.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;
}

正如@CraigTP在他的精彩回答中提到的,我也有类似的性能问题,使用exception来测试字符串是否是数值。因此,我最终分割字符串并使用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;
}
import java.util.Scanner;

public class TestDemo {
    public static void main(String[] args) {
        boolean flag = true;
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter the String:");
        String str = sc.nextLine();

        for (int i = 0; i < str.length(); i++) {
            if(str.charAt(i) > 48 && str.charAt(i) < 58) {
                flag = false;
                break;
            }
        }

        if(flag == true) {
            System.out.println("String is a valid String.");
        } else {
            System.out.println("String contains number.");
        }
    }
}

如果你在android上,那么你应该使用:

android.text.TextUtils.isDigitsOnly(CharSequence str)

文档可以在这里找到

保持简单。大多数人都可以“重新编程”(同样的事情)。