Examples:
"1" yes
"-1" yes
"- 3" no
"1.2" yes
"1.2.3" no
"7e4" no (though in some cases you may want to allow scientific notation)
".123" yes
"123." yes
"." no
"-.5" yes
"007" yes
"00" yes
Examples:
"1" yes
"-1" yes
"- 3" no
"1.2" yes
"1.2.3" no
"7e4" no (though in some cases you may want to allow scientific notation)
".123" yes
"123." yes
"." no
"-.5" yes
"007" yes
"00" yes
This allows for optional "+" and "-" in front. And allows trailing or initial whitespace.
/^\s*[+-]?(?:\d+\.?\d*|\d*\.\d+)\s*$/
Depending on the language you are coding in this functionality may already exist.
A Perl-compatible regex, allowing for optional sign (+/-), option trailing and initial whitespace, and not allowing things like '17.' or '-14.' which aren't valid decimal fractions. It does however allow things like '.5' or '-.7', which feel like valid decimal representations; if you don't want that, change the \d*
to \d+
.
/^\s*[-+]?(\d+|\d*\.\d+)\s*$/
Note that this tests for decimal fractions, not reals; strictly speaking there are reals which cannot be represented as decimal fractions (at least, in a finite space).
Matches all specified examples, doesn't capture any groups:
^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$
To not match "1." (etc):
^[+-]?(?:\d+(?:\.\d+)?|\.\d+)$
Doesn't bother with whitespace (use a trim function).
There are several alternatives. First, using a zero-width look-ahead assertion allows you to make the rest of the regex simpler:
/^[-+]?(?=\.?\d)\d*(?:\.\d*)?$/
If you want to avoid the look-ahead, then I'd try to discourage the regex from back-tracking:
/^[-+]?(?:\.\d+|\d+(?:\.\d*)?)$/
/^[-+]?(\.\d+|\d+(\.\d*)?)$/ # if you don't mind capturing parens
Note that you said "base 10" so you might actually want to disallow extra leading zeros since "014" might be meant to be octal:
/^[-+]?(?:\.\d+|(?:0|[1-9]\d*)(?:\.\d*)?)$/
/^[-+]?(\.\d+|(0|[1-9]\d*)(\.\d*)?)$/
Finally, you might want to replace \d
with [0-9]
since some regexes don't support \d
or because some regexes allow \d
to match Unicode "digits" other than 0..9 such as "ARABIC-INDIC DIGIT"s.
/^[-+]?(?:\.[0-9]+|(?:0|[1-9][0-9]*)(?:\.[0-9]*)?)$/
/^[-+]?(\.[0-9]+|(0|[1-9][0-9]*)(\.[0-9]*)?)$/
The regular expression in perlfaq4: How do I determine whether a scalar is a number/whole/integer/float? does what you want, and it handles the "e" notation too.
while( <DATA> ) { chomp; print /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/ ? "$_ Works\n" : "$_ Fails\n" ; } __DATA__ 1 -1 - 3 1.2 1.2.3 7e4 .123 123. . -.5