15

In javascript, how can you check if a string is a natural number (including zeros)?

Thanks

Examples:

'0' // ok
'1' // ok
'-1' // not ok
'-1.1' // not ok
'1.1' // not ok
'abc' // not ok
omega
  • 40,311
  • 81
  • 251
  • 474
  • http://stackoverflow.com/questions/3645544/checking-if-a-variable-is-an-integer-in-javascript – Harsha Venkataramu May 28 '13 at 19:05
  • Aren't natural numbers just non-negative integers? [Try `parseInt`](http://stackoverflow.com/questions/1133770/how-do-i-convert-a-string-into-an-integer-in-javascript)? [parseInt on Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/parseInt) – kush May 28 '13 at 19:05
  • @kush : parseInt? Does it do validation ? – Harsha Venkataramu May 28 '13 at 19:05
  • The problem with `parseInt()` (and `parseFloat()`) is that they accept junk after the numeric leading string, so `parseInt("15bananas")` is `15` and not an error. – Pointy May 28 '13 at 19:07
  • @kush: Some people include `0`. Others don't. – Blender May 28 '13 at 19:08
  • @Pointy : Exactly my point – Harsha Venkataramu May 28 '13 at 19:08
  • 2
    @kush [Wikipedia](http://en.wikipedia.org/wiki/Natural_number) (and one of my college professors from my college days) says that natural numbers may or may not include `0`, and always exclude negative numbers. In OP's case, the desired definition is noted to be inclusive of `0` (which is indeed "non-negative integers"). Also, `parseInt` alone won't work since `parseInt('1.1')` will return `1` (at least in Chrome). – ajp15243 May 28 '13 at 19:08
  • 6
    What about `1.0`? Is that a natural number by your definition? – Blender May 28 '13 at 19:23
  • Your theory of natural number is incorrect. – Virendra Singh Rathore Dec 06 '18 at 10:08

17 Answers17

25

Here is my solution:

function isNaturalNumber(n) {
    n = n.toString(); // force the value incase it is not
    var n1 = Math.abs(n),
        n2 = parseInt(n, 10);
    return !isNaN(n1) && n2 === n1 && n1.toString() === n;
}

Here is the demo:

var tests = [
        '0',
        '1',
        '-1',
        '-1.1',
        '1.1',
        '12abc123',
        '+42',
        '0xFF',
        '5e3'
    ];

function isNaturalNumber(n) {
    n = n.toString(); // force the value incase it is not
    var n1 = Math.abs(n),
        n2 = parseInt(n, 10);
    return !isNaN(n1) && n2 === n1 && n1.toString() === n;
}

console.log(tests.map(isNaturalNumber));

here is the output:

[true, true, false, false, false, false, false, false, false]

DEMO: http://jsfiddle.net/rlemon/zN6j3/1

Note: this is not a true natural number, however I understood it that the OP did not want a real natural number. Here is the solution for real natural numbers:

function nat(n) {
    return n >= 0 && Math.floor(n) === +n;
}

http://jsfiddle.net/KJcKJ/

provided by @BenjaminGruenbaum

Community
  • 1
  • 1
rlemon
  • 17,518
  • 14
  • 92
  • 123
  • I am updating this: it seems it fails on "+42". The solution is not the most elegant but works. – rlemon May 28 '13 at 19:33
  • +1 It might not the "the most elegant", but it's the only one here that works. – Benjamin Gruenbaum May 28 '13 at 19:40
  • @rlemon: You should fix `n1.toString.length === ...` – Blender May 28 '13 at 19:43
  • 1
    @Blender Honestly I'd just do `n>=0 && Math.floor(n) === +n`, this is what I consider natural numbers :) It's short, and it covers all edge cases by design – Benjamin Gruenbaum May 28 '13 at 19:50
  • @Blender, I thought I did (was typo). Looks like the edit was not taken. Thankyou. – rlemon May 28 '13 at 19:50
  • Also, It didn't occur to me that I was being redundant with the .toString().length and the .length check. That is also corrected. – rlemon May 28 '13 at 19:53
  • @BenjaminGruenbaum whereas yours is more accurate to what a natural number really is, I don't think it will satisfy the OPs requirements. But then again, maybe it will and the OP does not know this? – rlemon May 28 '13 at 20:00
  • 1
    @rlemon: You forgot the `var` keyword before `n2`. Without that, you're making `n2` global. – Blender May 28 '13 at 22:39
  • 2
    Blender, see the comma after n1 declaration. n2 is not global. – rlemon May 29 '13 at 11:00
  • Pretty cool, however here's a small issue. `+42` _is_ a natural number, yet the function evaluates to false when passed `+42`. – Octavian Helm May 29 '13 at 11:48
  • Not sure how this affects the use by the OP but this answer reports any string with leading zeros, such as 000 or 0023, as not natural. – HBP May 29 '13 at 11:52
  • But 5e3 and 0xFF *are* natural numbers. They're just different representations of natural numbers. – Dancrumb May 29 '13 at 12:12
  • It appeared to me the OP did not want those to pass. I have commented above that this is known and @BenjaminGruenbaum's fiddle is correct for the Natural Number validation. The OP is probably parsing some user input. As it appears however he has yet to comment on his actual intent. I will update if this is not the case. (the checkmark makes me think he wants this behavior) – rlemon May 29 '13 at 12:18
  • @rlemon - maybe I missed that requirement... I can't find where it says that. – Dancrumb May 29 '13 at 14:45
  • 1
    @Dancrumb Neither can I, I have updated my answer accordingly. I think the discussions in the comments may have confused me a bit on the requirements. Either way the OP knows the caveat of my function and has an alternative. – rlemon May 29 '13 at 17:04
  • @rlemon: `isNaturalNumber(undefined)` and `isNaturalNumber(null)` will crash, while `nat(null)` erroneously returns true. `nat(undefined)` correctly returns false. – Ron Martinez Jul 26 '14 at 19:46
  • Update to `const isNatNumber = (n) => (n > 0 || String(n) === "0") && Math.floor(n) === +n` To avoid `''` and `null` being parsed as zero. – Luca Fabbian Nov 30 '21 at 18:52
9

Use a regular expression

function isNaturalNumber (str) {
    var pattern = /^(0|([1-9]\d*))$/;
    return pattern.test(str);
}

The function will return either true or false so you can do a check based on that.

if(isNaturalNumber(number)){ 
   // Do something if the number is natural
}else{
   // Do something if it's not natural
}

Source: http://www.codingforums.com/showthread.php?t=148668

Chris Bier
  • 14,183
  • 17
  • 67
  • 103
  • 4
    does not work for `+42` or `5e3` or `0xFF` or ... long story short: numbers are more than text to parse – Jan Turoň May 28 '13 at 19:16
  • 1
    Right, and it doesn't have to, since that is not the OP's requirements. – Chris Bier May 28 '13 at 19:18
  • 1
    @ChrisB Sure it does. Those values satisfy a natural number. You shouldn't just code for examples – Ian May 28 '13 at 19:20
  • I am providing an answer based on the apparent needs of the OP, I am not required to satisfy anything further. I desire to keep it simple and to the point. If you feel my answer is insufficient then please post an answer. – Chris Bier May 28 '13 at 19:23
  • The answer is based on *some* of the needs of the OP. The way people show they feel an answer is insufficient is with downvotes, which I have run of votes for today. In your own words, I am not required to satisfy anything further, such as my own answer – Ian May 28 '13 at 19:35
  • oneliner: /^\d+$/.test(number) – Kamil Kiełczewski Nov 08 '16 at 19:00
7

If you have a regex phobia, you could do something like this:

function is_natural(s) {
    var n = parseInt(s, 10);

    return n >= 0 && n.toString() === s;
}

And some tests:

> is_natural('2')
true
> is_natural('2x')
false
> is_natural('2.0')
false
> is_natural('NaN')
false
> is_natural('0')
true
> is_natural(' 2')
false
Blender
  • 289,723
  • 53
  • 439
  • 496
  • It amazes me how many people aren't including the radix parameter – Ian May 28 '13 at 19:16
  • 1
    Whether `2.0` is or isn't a natural number is an interesting philosophical question :-) (Can a number be exactly equal to a natural number and yet not *be* a natural number? I'm not a mathematician.) – Pointy May 28 '13 at 19:16
  • @Pointy: Well, you *can* prove that 2 followed by an infinite string of zeroes after the decimal point is the number 2, just like 1 followed by an infinite string of 9's after the decimal point is also 2. – Blender May 28 '13 at 19:19
  • @Pointy I was thinking that as well, based on comments below tracevipin's answer, and [Wolfram defines natural numbers](http://mathworld.wolfram.com/NaturalNumber.html) as the set of positive (or non-negative) *integers*. Since `2.0` is not an integer, it is technically not a natural number (despite being equivalent to one of the natural numbers). – ajp15243 May 28 '13 at 19:24
  • @ajp15243: Why isn't it a natural number? It's both an integer and greater than 0/1 (depending on how you define the set of natural numbers). – Blender May 28 '13 at 19:25
  • @Blender I'm not convinced it's inherently an integer. I am open to seeing proof. – ajp15243 May 28 '13 at 19:31
  • @ajp15243: Can you explain how `1.0` differs from `1`? – Blender May 28 '13 at 19:32
  • @Blender Because it has a `.0`. Yes, `1.0 === 1`, but `1.0` could be seen as a different "entity" (for lack of a better word) than `1` because of its decimal component. I'm just saying I'm curious to see a formal and official definition for an integer involving the `.0` case, or at least a definition explaining that `1.0` does or does *not* differ from `1` as an "entity" due to or despite the decimal component. Basically I want the formal answer to Pointy's philosophical question. I guess this also gets down to if equality means they are the same "entity", given your comment to his question. – ajp15243 May 28 '13 at 19:42
  • @Blender I actually just read your comment that integers are a subset of rationals. I think that's a simple definition that I couldn't think of that ties it together for me, so it then follows that `1.0` is an integer and therefore a natural number. – ajp15243 May 28 '13 at 19:45
  • 1
    @ajp15243: The decimal point doesn't change the object that `1.0` refers to. By that same definition, would you argue that `1.0` and `1.00` are not equal? A somewhat related (and probably stronger) proof would be showing that `0.999... = 1`, which has [a lengthy Wikipedia article](https://en.wikipedia.org/wiki/0.999...). – Blender May 28 '13 at 19:46
2

You could use

var inN = !!(+v === Math.abs(~~v) && v.length);

The last test ensures '' gives false.

Note that it wouldn't work with very big numbers (like 1e14)

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
2

You can do if(num.match(/^\d+$/)){ alert(num) }

karthikr
  • 97,368
  • 26
  • 197
  • 188
1

You can check for int with regexp:

var intRegex = /^\d+$/;
if(intRegex.test(someNumber)) {
alert('Natural');
}
Goran Lepur
  • 594
  • 1
  • 4
  • 15
1
function isNatural(num){
    var intNum = parseInt(num);
    var floatNum = parseFloat(num);
    return (intNum == floatNum) && intNum >=0;
}
Diode
  • 24,570
  • 8
  • 40
  • 51
  • 2
    `2 == 2.0`, so your function will return `true` for `'2.0'`. – Blender May 28 '13 at 19:12
  • @Blender One could argue that `2.0` should be valid because of the very fact that `2 == 2.0`. Depends on what OP wants. – ajp15243 May 28 '13 at 19:15
  • @ajp15243 `2.0` isn't an integer, therefore isn't a natural number – Ian May 28 '13 at 19:17
  • @Ian: `2.0 === 2`, both in JS and in the mathematical sense. – Blender May 28 '13 at 19:20
  • @Ian True, forgot that detail in the [definition of a natural number](http://mathworld.wolfram.com/NaturalNumber.html) so I concede that point. The OP should probably make clear whether integer-equivalent numbers are included then (I'd guess not since they specified natural numbers, but they may not have thought of this case). – ajp15243 May 28 '13 at 19:21
  • @Blender Since I've seen links to Wikipedia, I might as well use it. It says natural numbers are non-negative integers. It says integers are "a number that can be written without a fractional or decimal component". So I guess `2.0` is considered an integer because it *can* be written without the decimal point. I was more or less trying to see if people had an argument against it, instead of assuming (and not providing an explanation in their answer) – Ian May 28 '13 at 19:23
  • 1
    @ajp15243 Absolutely, but at the same time, look at my comment right before this towards Blender. Maybe it should be valid. But you're right, it depends on how strict the OP "wants" this to be – Ian May 28 '13 at 19:24
  • 1
    @Ian As far as answers go, yes it is definitely up to the OP. For the mathematical definitions upon which much of these answers/comments/discussions are founded, I am interested to know if a number like `2.0` is considered an actual integer, or merely equivalent to an integer that is a "separate number entity". I imagine there is disagreement in the mathematical world. Perhaps a question for http://math.stackexchange.com/. – ajp15243 May 28 '13 at 19:28
  • @Blender I lied. Isn't `1.0` is considered a rational number? Just because `1.0 === 1` in JS doesn't mean it's true in math definitions – Ian May 28 '13 at 19:28
  • 1
    @Ian: Integers are a subset of rationals. `1.0` and `1` refer to the same object, just like `0` and `0.0` both refer to `0`. – Blender May 28 '13 at 19:31
  • @Blender See, we just need some explanation for a surprisingly controversial question. That seems to make sense, I just hadn't thought of it that way – Ian May 28 '13 at 19:37
1

Number() parses string input accurately. ("12basdf" is NaN, "+42" is 42, etc.). Use that to check and see if it's a number at all. From there, just do a couple checks to make sure that the input meets the rest of your criteria.

function isNatural(n) {
    if(/\./.test(n)) return false; //delete this line if you want n.0 to be true
    var num = Number(n);
    if(!num && num !== 0) return false;
    if(num < 0) return false;
    if(num != parseInt(num)) return false; //checks for any decimal digits
    return true;
}
user2000008
  • 120
  • 1
  • 11
1
function isNatural(n){
    return Math.abs(parseInt(+n)) -n === 0;
}

This returns false for '1 dog', '-1', '' or '1.1', and returns true

for non-negative integers or their strings, including '1.2345e12', and not '1.2345e3'.

kennebec
  • 102,654
  • 32
  • 106
  • 127
1

I know this thread is a bit old but I believe I've found the most accurate solution thus far:

function isNat(n) {                // A natural number is...
  return n != null                 // ...a defined value,
      && n >= 0                    // ...nonnegative,
      && n != Infinity             // ...finite,
      && typeof n !== 'boolean'    // ...not a boolean,
      && !(n instanceof Array)     // ...not an array,
      && !(n instanceof Date)      // ...not a date,
      && Math.floor(n) === +n;     // ...and whole.
}

My solution is basically an evolution of the contribution made by @BenjaminGruenbaum.

To back up my claim of accuracy I've greatly expanded upon the tests that @rlemon made and put every proposed solution including my own through them:

http://jsfiddle.net/icylace/qY3FS/1/

As expected some solutions are more accurate than others but mine is the only one that passes all the tests.

EDIT: I updated isNat() to rely less on duck typing and thus should be even more reliable.

Ron Martinez
  • 195
  • 4
  • 7
1

This is how I check if a string is a natural number (including zeros!).

var str = '0' // ok
var str1 = '1' // ok
var str2 = '-1' // not ok
var str3 = '-1.1' // not ok
var str4 = '1.1' // not ok
var str5 = 'abc' // not ok

console.log("is str natural number (including zeros): ", Number.isInteger(Number(str)) && Number(str) >= 0)
console.log("is str1 natural number (including zeros): ", Number.isInteger(Number(str1)) && Number(str1) >= 0)
console.log("is str2 natural number (including zeros): ", Number.isInteger(Number(str2)) && Number(str2) >= 0)
console.log("is str3 natural number (including zeros): ", Number.isInteger(Number(str3)) && Number(str3) >= 0)
console.log("is str4 natural number (including zeros): ", Number.isInteger(Number(str4)) && Number(str4) >= 0)
console.log("is str5 natural number (including zeros): ", Number.isInteger(Number(str5)) && Number(str5) >= 0)
edzillion
  • 3,592
  • 5
  • 31
  • 50
Md. Robi Ullah
  • 1,703
  • 3
  • 20
  • 32
1
const func = (number) => {
    return Math.floor(number) === number
}
Ash
  • 11
  • 1
0

Convert the string to a number and then check:

function isNatural( s ) {
  var n = +s;
  return !isNaN(n) && n >= 0 && n === Math.floor(n);
}
Pointy
  • 405,095
  • 59
  • 585
  • 614
0
function isNatural(number){
    var regex=/^\d*$/;
    return regex.test( number );
}
McNally Paulo
  • 192
  • 1
  • 8
0
function isNatural(n) {
 return Number(n) >= 0 && Number(n) % 1 === 0;
}
Oleg
  • 161
  • 1
  • 5
  • 1
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Mark Rotteveel Aug 26 '22 at 15:08
  • 1
    This answer was reviewed in the [Low Quality Queue](https://stackoverflow.com/help/review-low-quality). Here are some guidelines for [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer). Code only answers are **not considered good answers**, and are likely to be downvoted and/or deleted because they are **less useful** to a community of learners. It's only obvious to you. Explain what it does, and how it's different / **better** than existing answers. [From Review](https://stackoverflow.com/review/low-quality-posts/32577275) – Trenton McKinney Aug 26 '22 at 19:55
0

Why not simply use modulo? if(num % 1 !== 0) return false;

jdd2405
  • 13
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 25 '22 at 10:11
-1

Use /^\d+$/ will match 000. so use /^[1-9]\d*$|^0$/ match positive integer or 0 will be right.

xskxzr
  • 12,442
  • 12
  • 37
  • 77