1

I have multiple strings that may or may not be equal to a double value (e.g. "444", "44.4", "-0.0044"). I was wondering what the most efficient way would be to check if it is equal to a double. At first I was using a try-catch statement but other posts on StackOverflow have said that those are costly to performance if an exception is thrown. Here is the code I have so far:

try { 
     double a = Double.parseDouble("444");
     return true;
}
catch (NumberFormatException e) {
     return false;
}
vallentin
  • 23,478
  • 6
  • 59
  • 81
user3015565
  • 393
  • 3
  • 6
  • 16
  • Have you checked http://stackoverflow.com/questions/3543729/java-how-to-check-that-a-string-is-parsable-to-a-double – Mani Jan 07 '14 at 00:23
  • Since you do not have a method, you can not simply add return statements. Instead you could do this try { d = Double.parseDouble(string); } catch (NumberFormatException ex) { // do something here } – nmargaritis Jan 07 '14 at 00:24
  • @NikosMargaritis but they want to avoid throwing the Exception in the first place – Java Devil Jan 07 '14 at 00:25
  • @JavaDevil then he should test the string over a specified pattern before parsing it. – nmargaritis Jan 07 '14 at 00:27
  • @NikosMargaritis Which is exactly the kind of answer they were looking for... not the same code again. – Java Devil Jan 07 '14 at 00:30
  • @JavaDevil somebody gave the answer already, however, the reason I made the comment in the first place is related with the fact of the return statements and not with the answer. That's why I comment and didnt answer the question. – nmargaritis Jan 07 '14 at 00:33

3 Answers3

3

Java specifies a regular expression that can be used to validate strings being passed to Double.parseDouble or Double.valueOf in the Javadoc of Double.valueOf:

final String Digits     = "(\\p{Digit}+)";
final String HexDigits  = "(\\p{XDigit}+)";
// an exponent is 'e' or 'E' followed by an optionally
// signed decimal integer.
final String Exp        = "[eE][+-]?"+Digits;
final String fpRegex    =
  ("[\\x00-\\x20]*"+  // Optional leading "whitespace"
   "[+-]?(" + // Optional sign character
   "NaN|" +           // "NaN" string
   "Infinity|" +      // "Infinity" string

   // A decimal floating-point string representing a finite positive
   // number without a leading sign has at most five basic pieces:
   // Digits . Digits ExponentPart FloatTypeSuffix
   //
   // Since this method allows integer-only strings as input
   // in addition to strings of floating-point literals, the
   // two sub-patterns below are simplifications of the grammar
   // productions from section 3.10.2 of
   // The Java™ Language Specification.

   // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
   "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+

   // . Digits ExponentPart_opt FloatTypeSuffix_opt
   "(\\.("+Digits+")("+Exp+")?)|"+

   // Hexadecimal strings
   "((" +
    // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
    "(0[xX]" + HexDigits + "(\\.)?)|" +

    // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
    "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +

    ")[pP][+-]?" + Digits + "))" +
   "[fFdD]?))" +
   "[\\x00-\\x20]*");// Optional trailing "whitespace"

 if (Pattern.matches(fpRegex, myString))
   Double.valueOf(myString); // Will not throw NumberFormatException
 else {
   // Perform suitable alternative action
 }
Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
1

If (as the title suggests) you are testing that a String equals a particular double, the simplest and fastest way is to convert the double to a String and then compare:

if (Double.toString(d).equals(s))

rather than dealing with the vagaries and exceptions of parsing a string.


If as your code suggests, you are testing if a String could be parsed (as any double), the code you have now is probably the best way to go. Parsing floating point numbers is quite complex and the work must be done somewhere - might as well let the API do the work. Also, throwing an exception is not that expensive.

Only seek to optimize for performance if your current working implementation is proven to be too slow to be tolerable. Unless you are parsing hundreds of these per second, I wouldn't worry.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • By my reading, the OP is looking to see if a String is equal to *any* double, rather than if it's equal to a *specific* double. (That confused me, too.) – ruakh Jan 07 '14 at 01:06
  • @ruakh oh... I think you're right. So he means "can be parsed as any double" – Bohemian Jan 07 '14 at 01:08
0

Past answers to this question say to use a pre-compiled RegEx using the pattern from the API docs

Pattern redbl=Pattern.compile("[\\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 isDouble=redbl.matcher("444.123").matches();
EkriirkE
  • 2,277
  • 19
  • 13