如何在Java中检查一个字符串是否是数字

1047

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


42
所有使用正则表达式提出的解决方案都不能用于十六进制数字。 - Oscar Castiblanco
在编程中,传递空字符串到matches(...)函数将会抛出NullPointer异常。 - Hitesh Sahu
请参考Max Malysh的答案,其中提供了一个简洁的Java 8解决方案,无需使用第三方库。 - Andy Thomas
@HiteshSahu 最新版本(包括Java 6.x和7.x)似乎能够优雅地处理null字符串。 - lifebalance
所有提出使用Integer.parseInt()的解决方案都无法正确解析包含“NumberFormatException”的移动电话号码。 - Not a bug
@OscarCastiblanco 在给定的基数中,_所有_字符串都是数字。 - bfontaine
41个回答

1

试试这个:

public  boolean isNumber(String str)
{       
    short count = 0;
    char chc[]  = {'0','1','2','3','4','5','6','7','8','9','.','-','+'};
    for (char c : str.toCharArray())
    {   
        for (int i = 0;i < chc.length;i++)
        {
            if( c  == chc[i]){
                count++;        
            }
         }                      
    }
    if (count != str.length() ) 
        return false;
    else
        return true;
}

1
你可以使用 BigDecimal 如果字符串可能包含小数:
try {
    new java.math.BigInteger(testString);
} catch(NumberFormatException e) {
    throw new RuntimeException("Not a valid number");
}

6
欢迎来到Stack Overflow。通常情况下,最好避免唤起旧的帖子,除非回复在主题上有显著不同之处。虽然有效,但这种方法已经在被接受的答案中提到过了。 - Leigh
如果您不记录异常,这将会创建一个声纳问题。 - jmhostalet

1

使用IntStream并行检查非常长的字符串

在Java 8中,以下代码测试给定string的所有字符是否都在'0'到'9'之间。注意,空字符串也会被接受:

string.chars().unordered().parallel().allMatch( i -> '0' <= i && '9' >= i )

1
以下是两种可能有效的方法。(不使用异常) 注意: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;
}

哦,好问题。我猜这个方法只适用于普通类型的整数。最初创建该方法是为了过滤输入的电话号码,并计算数字。 - XForCE07

1
如果您想使用正则表达式进行检查,应创建一个最终的静态Pattern对象,这样正则表达式只需要编译一次。编译正则表达式需要与执行匹配相同的时间,因此通过采取这种预防措施,您将减少该方法的执行时间一半。
final static Pattern NUMBER_PATTERN = Pattern.compile("[+-]?\\d*\\.?\\d+");

static boolean isNumber(String input) {
    Matcher m = NUMBER_PATTERN.matcher(input);
    return m.matches();
}

我假设一个数字是一个字符串,它只包含十进制数字,可能在开头有一个+或-符号,并且最多有一个小数点(不在末尾),没有其他字符(包括逗号、空格、其他计数系统中的数字、罗马数字、象形文字)。
这个解决方案简洁而且相当快,但是您可以通过像这样执行来缩短每百万次调用的几毫秒。
static boolean isNumber(String s) {
    final int len = s.length();
    if (len == 0) {
        return false;
    }
    int dotCount = 0;
    for (int i = 0; i < len; i++) {
        char c = s.charAt(i);
        if (c < '0' || c > '9') {
            if (i == len - 1) {//last character must be digit
                return false;
            } else if (c == '.') {
                if (++dotCount > 1) {
                    return false;
                }
            } else if (i != 0 || c != '+' && c != '-') {//+ or - allowed at start
                return false;
            }

        }
    }
    return true;
}

1

我认为可靠地判断字符串是否是一个数字的唯一方法就是解析它。所以我会直接解析它,如果它是一个数字,你就可以免费得到一个整数!


1
这是我知道的检查字符串是否为数字的最快方法:
public static boolean isNumber(String str){
  int i=0, len=str.length();
  boolean a=false,b=false,c=false, d=false;
  if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-')) i++;
  while( i<len && isDigit(str.charAt(i)) ){ i++; a=true; }
  if(i<len && (str.charAt(i)=='.')) i++;
  while( i<len && isDigit(str.charAt(i)) ){ i++; b=true; }
  if(i<len && (str.charAt(i)=='e' || str.charAt(i)=='E') && (a || b)){ i++; c=true; }
  if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-') && c) i++;
  while( i<len && isDigit(str.charAt(i)) ){ i++; d=true;}
  return i==len && (a||b) && (!c || (c && d));
}
static boolean isDigit(char c){
  return c>='0' && c<='9';
}

1
我们可以简单地使用以下方式,而不是进行这么多的检查: if (ch >= '0' && ch <= '9') {} - jettimadhuChowdary

0

如果你们使用以下方法进行检查:

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

结果是"true",同时它也是一个太大的数字! 如果你使用正则表达式来检查,同样会发生这种情况! 因此,我更倾向于使用"解析"方法进行检查,就像这样:
public static boolean isNumeric(String str) {
    try {
        int number = Integer.parseInt(str);
        return true;
    } catch (Exception e) {
        return false;
    }
}

结果和我预期的一样!


1
“it is a too-large-size number” → 没有所谓的“太大的数字”。数字是无限的。7645是一个数字,92847294729492875982452012471041141990140811894142729051也是一个数字。第一个可以表示为Integer,第二个可以表示为BigDecimal。即使它们不能在Java中表示为对象,它们仍然是数字--这就是问题所问的。 - walen
另外,不要滥用异常。Java 不是 Python。至少使用更具体的 NumberFormatException - Jiří

0
private static Pattern p = Pattern.compile("^[0-9]*$");

public static boolean isNumeric(String strNum) {
    if (strNum == null) {
        return false;
    }
    return p.matcher(strNum).find();
}

2
虽然这段代码可能解决了问题,但是包括解释它如何以及为什么解决了问题将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释并指出适用的限制和假设。 - Yunnosch

0
String text="hello 123";
if(Pattern.matches([0-9]+))==true
System.out.println("String"+text);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接