如何确定字符串中包含的值是否为double

时间:2010-06-28 15:31:05

标签: java

在Java中,我试图找出字符串中包含的值是否为double?

14 个答案:

答案 0 :(得分:31)

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

答案 1 :(得分:13)

source for Double中有关于此的说明:

  

[...] 为避免在无效字符串上调用此方法并抛出NumberFormatException,可以使用下面的正则表达式来筛选输入字符串: [。 ..]

后面的正则表达式的最终形式很长:

[\x00-\x20]*[+-]?(NaN|Infinity|((((\p{Digit}+)(\.)?((\p{Digit}+)?)([eE][+-]?(\p{Digit}+))?)|(\.((\p{Digit}+))([eE][+-]?(\p{Digit}+))?)|(((0[xX](\p{XDigit}+)(\.)?)|(0[xX](\p{XDigit}+)?(\.)(\p{XDigit}+)))[pP][+-]?(\p{Digit}+)))[fFdD]?))[\x00-\x20]*

但是,使用此方法,您可以轻松地排除Infinity接受的NaNDouble.parseDouble等特殊双打。例如:

String regExp = "[\\x00-\\x20]*[+-]?(((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)|(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*";
boolean matches = yourString.matches(regExp);

答案 2 :(得分:7)

您可以创建Scanner(String)并使用hasNextDouble()方法。来自它的javadoc:

  

如果此扫描仪输入中的下一个标记可以,则返回true   解释为使用的双值   nextDouble()方法。扫描仪   没有超越任何输入。

例如,此代码段:

List<String> values = Arrays.asList("foo", "1", "2.3", "1f", "0.2d", "3.14");
for (String source : values) {
    Scanner scanner = new Scanner(source);
    System.out.println(String.format("%4s: %s", source, scanner.hasNextDouble()));
}

会产生以下输出:

 foo: false
   1: true
 2.3: true
  1f: false
0.2d: false
3.14: true

答案 3 :(得分:7)

使用Scanner将明显慢于使用Double.parseDouble(String s)

private static Random rand = new Random();
private static final String regExp = "[\\x00-\\x20]*[+-]?(((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)([eE][+-]?(\\p{Digit}+))?)|(\\.((\\p{Digit}+))([eE][+-]?(\\p{Digit}+))?)|(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*";
private static final Pattern pattern = Pattern.compile(regExp);

public static void main(String[] args) {

    int trials = 50000;
    String[] values = new String[trials];

    // initialize the array
    // about half the values will be parsable as double
    for( int i = 0; i < trials; ++i ) {
        double d = rand.nextDouble();
        boolean b = rand.nextBoolean();

        values[i] = (b ? "" : "abc") + d;
    }

    long start = System.currentTimeMillis();

    int parseCount = 0;
    for( int i = 0; i < trials; ++i ) {
        if( isDoubleParse(values[i]) ) {
            parseCount++;
        }
    }

    long end = System.currentTimeMillis();
    long elapsed = end - start;

    System.out.println("Elapsed time parsing: " + elapsed + " ms");
    System.out.println("Doubles: " + parseCount);

    // reset the timer for the next run
    start = System.currentTimeMillis();

    int scanCount = 0;
    for( int i = 0; i < trials; ++i ) {
        if( isDoubleScan(values[i]) ) {
            scanCount++;
        }
    }

    end = System.currentTimeMillis();
    elapsed = end - start;

    System.out.println("Elapsed time scanning: " + elapsed + " ms");
    System.out.println("Doubles: " + scanCount);


    // reset the timer for the next run
    start = System.currentTimeMillis();

    int regexCount = 0;
    for( int i = 0; i < trials; ++i ) {
        if( isDoubleRegex(values[i]) ) {
            regexCount++;
        }
    }

    end = System.currentTimeMillis();
    elapsed = end - start;

    System.out.println("Elapsed time regex (naive): " + elapsed + " ms");
    System.out.println("Doubles: " + naiveRegexCount);


    // reset the timer for the next run
    start = System.currentTimeMillis();

    int compiledRegexCount = 0;
    for( int i = 0; i < trials; ++i ) {
        if( isDoubleCompiledRegex(values[i]) ) {
            compiledRegexCount++;
        }
    }

    end = System.currentTimeMillis();
    elapsed = end - start;

    System.out.println("Elapsed time regex (compiled): " + elapsed + " ms");
    System.out.println("Doubles: " + compiledRegexCount);
}


public static boolean isDoubleParse(String s) {
    if( s == null ) return false;
    try {
        Double.parseDouble(s);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

public static boolean isDoubleScan(String s) {
    Scanner scanner = new Scanner(s);
    return scanner.hasNextDouble();
}

public static boolean isDoubleRegex(String s) {
    return s.matches(regExp);
}

public static boolean isDoubleCompiledRegex(String s) {
    Matcher m = pattern.matcher(s);
    return m.matches();
}

当我运行上面的代码时,我得到以下输出:

  

经过时间分析:235毫秒
  双打:24966
  经过时间扫描:31358毫秒
  双打:24966
  经过时间正则表达式(天真):1829毫秒
  双打:24966
  经过时间正则表达式(编译):109毫秒
  双打:24966

由于正则表达式的复杂性,正则表达式方法运行得相当快,但仍然不如使用Double.parseDouble(s)进行简单解析那么快。正如评论中所指出的那样,有一些像NaN这样的值可以通过解析器,但可能不应该这样。

更新

根据@ Gabe的建议预编译正则表达式会有所不同。编译的正则表达式方法现在是明显的赢家。

答案 4 :(得分:6)

public boolean isDouble(String value) {
    try {
        Double.parseDouble(value);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

答案 5 :(得分:5)

您可以使用Apache Commons Lang的util类:

NumberUtils.isNumber(aString);

它是安全的,并且不需要使用try-catch块。

注意:用于解析双精度数,如果小数点分隔符是点.

,则它可以工作

编辑: isNumber已弃用,将从Lang 4.0中删除

最好使用:

NumberUtils.isCreatable(aString);

答案 6 :(得分:2)

您可以尝试使用Double.parseDouble(String s)

解析它

如果解析成功则返回double,如果不可解析则返回异常。

因此,您可以将整个事物包装在包含try-catch的函数中,如果有异常则返回false,如果获得实际值则返回true。

答案 7 :(得分:2)

我会建议:

try {
  d = Double.parseDouble(myString);
}
catch (NumberFormatException ex) {
    // Do something smart here...
}

答案 8 :(得分:2)

其他人猜测你可能也想知道输入没有表示为整数。根据您的要求,这可能会使工作变得快速而且肮脏:

public static void main(String[] args) throws Exception {
    System.out.println(isNonIntegerDouble("12"));  //false
    System.out.println(isNonIntegerDouble("12.1")); //true
    System.out.println(isNonIntegerDouble("12.0")); //true
}

public static boolean isNonIntegerDouble(String in) {
    try {
        Double.parseDouble(in);
    } catch (NumberFormatException nfe) {
        return false;
    }
    try {
        new BigInteger(in);
    } catch (NumberFormatException nfe) {
        return true;
    }
    return false;
}

此时我觉得字符串匹配是更合适的选择。

答案 9 :(得分:1)

您可以在字符串上使用以下正则表达式:

[-+]?[0-9]*\.?[0-9]*

并查看它是否匹配。

答案 10 :(得分:1)

  

我们必须处理NumberFormatException和null指针异常,以检查给定的String是数字还是字母数字

public static boolean isNumeric(String strNum) {
        try {
           Double.parseDouble(strNum);
        } catch (NumberFormatException | NullPointerException nfe) {
            return false;
        }
        return true;
    }

答案 11 :(得分:0)

我修改了Jonas的isInteger()方法,为我自己的项目提出了方法isDecimal(),我列出了下面的代码。

可能有人可以更改添加更多代码来区分double和float。

虽然我没有检查,它应该很快出来,可能比正则表达更好。唯一的缺陷是在溢出情况等情况下行为不端。

请注意,我在What's the best way to check to see if a String represents an integer in Java?

上提到了Bill的帖子
    public boolean isDecimal(String str) {
        if (str == null) {
            return false;
        }
        int length = str.length();
        if (length == 1 ) {
            return false;
        }
        int i = 0;
        if (str.charAt(0) == '-') {
            if (length < 3) {
                return false;
            }
            i = 1;
        }
        int numOfDot = 0;
        for (; i < length; i++) {
            char c = str.charAt(i);
            if (c == '.')
                numOfDot++;
            else if (c == '/')
                return false;
            else if (c < '.' || c > '9') {
                return false;
            }
        }
        if (numOfDot != 1 )
            return false;

        return true;
    }

答案 12 :(得分:0)

如果您能找到一种方法将数字与字符串隔离,可以使用split方法。然后让我们说deriv()然后你可以做这样的事情来检查它是否是双倍的。

public static void jsonToMap(String t) throws JSONException {

    HashMap<String, String> map = new HashMap<String, String>();
    JSONObject jObject = new JSONObject(t);
    Iterator<?> keys = jObject.keys();

    while( keys.hasNext() ){
        String key = (String)keys.next();
        String value = jObject.getString(key); 
        map.put(key, value);
    }

    System.out.println("json : "+jObject);
    System.out.println("map : "+map);
}

答案 13 :(得分:-3)

    public boolean isDouble( String input )  
    {  
       try  
       {  
          Double.parseDouble( input );  
          return true;  
       }  
       catch( Exception e)  
       {  
         return false;  
      }  
  }