views:

128

answers:

3

Hi All, Would be grateful your help.

What would be elegant Regx to check a String whether it holds a number ? any suggestions? thanks.

+3  A: 

Take a look at the implementation of the Apache's NumberUtils.isNumber. I wouldn't recommend using regular expressions for such validation.

Alex Nikolaenkov
Is number just checks if all characters in the string are digits. Even the empty string `isNumber`.
aioobe
isDigits does it. isNumber is much more sophisticated. isNumber checks whether some string can be parsed as number.
Alex Nikolaenkov
+8  A: 

I don't think that an exception (even if it is triggered) is that much more expensive than a regular expression - you'd have to profile it and see if it really makes a difference.

That said, a regular expression that implements the BigDecimal grammar according to the Java Docs is

[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?

Explanation:

[+-]?       # optional sign
(?:         # required significand: either...
 \d+        # a number
 (?:\.\d*)? # optionally followed by a dot, optionally followed by more digits
 |          # or...
 \.\d+      # just a dot, followed by digits (in this case required)
)           # end of significand
(?:         # optional exponent
 [eE]       # required exponent indicator
 [+-]?      # optional sign
 \d+        # required digits
)?          # end of exponent

If you want to allow different number formats (and thousands separators) you could first get those values from DecimalFormatSymbols and build your regex with it.

Something like this (I don't know Java, so feel free to correct my Syntax Errors):

// you need java.util.regex.Pattern and java.text.DecimalFormatSymbols
string ds = Pattern.quote(DecimalFormatSymbols.getDecimalSeparator())
string gs = Pattern.quote(DecimalFormatSymbols.getGroupingSeparator())
string ms = Pattern.quote(DecimalFormatSymbols.getMinusSign())
string es = Pattern.quote(DecimalFormatSymbols.getExponentSeparator())

string myre = 
    "(?xi)\n       # verbose, case-insensitive regex" +
    "[+" +ms+ "]?  # optional sign\n" +
    "(?:           # required significand: either...\n" +
    " (?:\\d{1,3}(?:" +gs+ "\\d{3}|\\d++) # a number with optional thousand separators,\n" +
    " (?:" +ds+ "\\d*)? # optionally followed by a dot, optionally followed by more digits\n" +
    " |            # or...\n" +
      ds+ "\\d+    # just a dot, followed by digits (in this case required)\n" +
    ")             # end of significand\n" +
    "(?:           # optional exponent\n" +
      es+ "        # required exponent indicator\n" +
    " [+" +ms+ "]? # optional sign\n" +
    " \\d+         # required digits\n" +
    ")?            # end of exponent"

boolean foundMatch = subjectString.matches(myregex);

You could then replace the locale-dependent bits back into their US counterparts before handing the number over for BigDecimal conversion, if that's not locale-aware.

Tim Pietzcker
OK, I have updated my answer.
Tim Pietzcker
+2  A: 

Do not use regular expressions, they almost always are not the answer to any problem. You might accept some regex and then later on find out that it does not cover all situations. If you really want to know if a string has a BigDecimal, why not ask the source BigDecimal itself, after all it by definition is always right while using a regular expression cant always be right, you might just get it wrong.

mP