I would like the simplest fail-safe test to check that a string in JavaScript is a positive integer.
isNaN(str)
returns true for all sorts of non-integer values and parseInt(str)
is returning integers for float strings, like "2.5". And I don't want to have to use some jQuery plugin either.
Simple
You can also extend Number and assign the function to it via prototype.
Looks like a regular expression is the way to go:
(~~a == a)
wherea
is the string.won't work if you give a string like '0001' though
Just to build on VisioN's answer above, if you are using the jQuery validation plugin you could use this:
Then you could use in your normal rules set or add it dynamically this way:
Two answers for you:
Based on parsing
Regular expression
Note that in both cases, I've interpreted "positive integer" to include
0
, even though0
is not positive. I include notes if you want to disallow0
.Based on Parsing
If you want it to be a normalized decimal integer string over a reasonable range of values, you can do this:
or if you want to allow whitespace and leading zeros:
Live testbed (without handling leading zeros or whitespace):
Live testbed (with handling for leading zeros and whitespace):
If you want to disallow
0
, just change>= 0
to> 0
. (Or, in the version that allows leading zeros, remove the|| "0"
on thereplace
line.)How that works:
In the version allowing whitespace and leading zeros:
str = str.trim();
removes any leading and trailing whitepace.if (!str)
catches a blank string and returns, no point in doing the rest of the work.str = str.replace(/^0+/, "") || "0";
removes all leading 0s from the string — but if that results in a blank string, restores a single 0.Number(str)
: Convertstr
to a number; the number may well have a fractional portion, or may beNaN
.Math.floor
: Truncate the number (chops off any fractional portion).String(...)
: Converts the result back into a normal decimal string. For really big numbers, this will go to scientific notation, which may break this approach. (I don't quite know where the split is, the details are in the spec, but for whole numbers I believe it's at the point you've exceeded 21 digits [by which time the number has become very imprecise, as IEEE-754 double-precision numbers only have roughtly 15 digits of precision..)... === str
: Compares that to the original string.n >= 0
: Check that it's positive.Note that this fails for the input
"+1"
, any input in scientific notation that doesn't turn back into the same scientific notation at theString(...)
stage, and for any value that the kind of number JavaScript uses (IEEE-754 double-precision binary floating point) can't accurately represent which parses as closer to a different value than the given one (which includes many integers over 9,007,199,254,740,992; for instance,1234567890123456789
will fail). The former is an easy fix, the latter two not so much.Regular Expression
The other approach is to test the characters of the string via a regular expression, if your goal is to just allow (say) an optional
+
followed by either0
or a string in normal decimal format:Live testbed:
How that works:
^
: Match start of string\+?
: Allow a single, optional+
(remove this if you don't want to)(?:...|...)
: Allow one of these two options (without creating a capture group):(0|...)
: Allow0
on its own...(...|[1-9]\d*)
: ...or a number starting with something other than0
and followed by any number of decimal digits.$
: Match end of string.If you want to disallow
0
(because it's not positive), the regular expression becomes just/^\+?[1-9]\d*$/
(e.g., we can lose the alternation that we needed to allow0
).If you want to allow leading zeroes (0123, 00524), then just replace the alternation
(?:0|[1-9]\d*)
with\d+
If you want to allow whitespace, add
\s*
just after^
and\s*
just before$
.Note for when you convert that to a number: On modern engines it would probably be fine to use
+str
orNumber(str)
to do it, but older ones might extend those in a non-standard (but formerly-allowed) way that says a leading zero means octal (base 8), e.g "010" => 8. Once you've validated the number, you can safely useparseInt(str, 10)
to ensure that it's parsed as decimal (base 10).parseInt
would ignore garbage at the end of the string, but we've ensured there isn't any with the regex.