Tutorial :How to find out if the value contained in a string is double or not



Question:

In Java, I am trying to find out if the value contained in a string is double or not?


Solution:1

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


Solution:2

There is a note about this in the source for Double:

[...] To avoid calling this method on a invalid string and having a NumberFormatException be thrown, the regular expression below can be used to screen the input string: [...]

The final form of the regular expressions that follows is quite long:

[\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]*  

Using this method however, you can easily exclude some special doubles such as Infinity and NaN which are both accepted by Double.parseDouble. For example like this:

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


Solution:3

You could create a Scanner(String) and use the hasNextDouble() method. From its javadoc:

Returns true if the next token in this scanner's input can be interpreted as a double value using the nextDouble() method. The scanner does not advance past any input.

For example, this snippet:

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

Would produce the following output:

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


Solution:4

Using a Scanner will be significantly slower than using 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();  }  

When I run the code above I get the following output:

Elapsed time parsing: 235 ms
Doubles: 24966
Elapsed time scanning: 31358 ms
Doubles: 24966
Elapsed time regex (naive): 1829 ms
Doubles: 24966
Elapsed time regex (compiled): 109 ms
Doubles: 24966

The regular expression method runs fairly quickly given the complexity of the regex, but still not quite as fast as simply parsing using Double.parseDouble(s). As pointed out in the comments, there are a few values like NaN that get past the parser that probably shouldn't.

Update:

Pre-compiling the regular expression as suggested by @Gabe makes all the difference. The compiled regex method is now the clear winner.


Solution:5

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


Solution:6

You can use util class from Apache Commons Lang:

NumberUtils.isNumber(aString);  

It's null safe and doesn't require the use of a try-catch block.

Note: for parsing doubles, it works if the decimal separator is a dot .

Edit: isNumber is Deprecated and will be removed from Lang 4.0

Better to use:

NumberUtils.isCreatable(aString);  


Solution:7

You could attempt to parse it with Double.parseDouble(String s)

This will return the double if parsing was successful and an an exception if it is not parseable.

So you could wrap the whole thing in a function that contains a try-catch, and return false if you got an exception or true if you got an actual value.


Solution:8

I would suggest this:

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


Solution:9

Others have speculated that you might want to also know that the input is NOT expressed as an integer. Depending on your requirements, this might do the job quick and dirty:

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

At this point I feel string matching would be a more suitable choice, however.


Solution:10

You could use the following regex on the string:

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

and see if it matches.


Solution:11

I modified Jonas' isInteger() method to come up with the method isDecimal() for my own project and I'm listing the codes below.

May be someone can change add more codes to distinguish between a double and a float.

It should come out pretty speedy and probably better than regex, though I haven't check. The only flaw is it misbehaves in case of overflow condition, etc.

Note that I reference Bill's post at What's the best way to check to see if a String represents an integer in Java?

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


Solution:12

If you could find a way to isolate the number from the string, maybe by using split method. And lets say num[1] = 25; then you could do something like this to check if its a double.

boolean isDouble;  if(num[1].contains(".")){  isDouble = true;  }  else{  isDouble = false;  }  


Solution:13

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

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »