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


当前回答

如果您想使用正则表达式进行检查,则应该创建一个最终的静态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;
}

其他回答

这就是为什么我喜欢。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.
}

这是我知道的最快的方法来检查字符串是否为数字:

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

如果你使用java开发Android应用程序,你可以使用TextUtils。isDigitsOnly函数。

这通常是通过一个简单的用户定义函数来完成的(例如,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.
}

但是要小心上面的RegEx机制,因为如果你使用非阿拉伯数字(即0到9以外的数字),它会失败。这是因为RegEx的“\d”部分只匹配[0-9],并且有效地不具有国际数字意识。(感谢OregonGhost指出这一点!)

甚至另一种替代方法是使用Java内置的Java .text. numberformat对象来查看解析字符串后解析器的位置是否位于字符串的末尾。如果是,我们可以假设整个字符串都是数字:

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

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

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

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