How can I check if a string is a valid number?
Asked Answered
M

56

1949

I'm hoping there's something in the same conceptual space as the old VB6 IsNumeric() function?

Mascagni answered 6/10, 2008 at 19:12 Comment(8)
See this related question, which I asked some time ago.Spatola
If you go to this question, try to skip past all the RegEx answers. That's just NOT the way to do it.Illassorted
Unless one wants to do exactly that: To check whether a given string has a format of a valid stream of digits. Why should it be wrong then?Upgrowth
The selected answer is incorrect!!! See its comments, but basically it fails with e.g. isNaN(""), isNaN(" "), isNaN(false), etc. It returns false for these, implying that they are numbers.Organdy
so the selected answer is incorrect, regexp is not the way to do that neither. Which one is correct then?Shod
which one is correct?Lyon
Not built in, but... JQuery has a well tested one api.jquery.com/jquery.isnumericSiqueiros
Probably, the question should be `how to check whether a string is a valid number representation?'.Scharff
T
3212

2nd October 2020: note that many bare-bones approaches are fraught with subtle bugs (eg. whitespace, implicit partial parsing, radix, coercion of arrays etc.) that many of the answers here fail to take into account. The following implementation might work for you, but note that it does not cater for number separators other than the decimal point ".":

function isNumeric(str) {
  if (typeof str != "string") return false // we only process strings!  
  return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
         !isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail
}

To check if a variable (including a string) is a number, check if it is not a number:

This works regardless of whether the variable content is a string or number.

isNaN(num)         // returns true if the variable does NOT contain a valid number

Examples

isNaN(123)         // false
isNaN('123')       // false
isNaN('1e10000')   // false (This translates to Infinity, which is a number)
isNaN('foo')       // true
isNaN('10px')      // true
isNaN('')          // false
isNaN(' ')         // false
isNaN(false)       // false

Of course, you can negate this if you need to. For example, to implement the IsNumeric example you gave:

function isNumeric(num){
  return !isNaN(num)
}

To convert a string containing a number into a number:

Only works if the string only contains numeric characters, else it returns NaN.

+num               // returns the numeric value of the string, or NaN 
                   // if the string isn't purely numeric characters

Examples

+'12'              // 12
+'12.'             // 12
+'12..'            // NaN
+'.12'             // 0.12
+'..12'            // NaN
+'foo'             // NaN
+'12px'            // NaN

To convert a string loosely to a number

Useful for converting '12px' to 12, for example:

parseInt(num)      // extracts a numeric value from the 
                   // start of the string, or NaN.

Examples

parseInt('12')     // 12
parseInt('aaa')    // NaN
parseInt('12px')   // 12
parseInt('foo2')   // NaN      These last three may
parseInt('12a5')   // 12       be different from what
parseInt('0x10')   // 16       you expected to see.

Floats

Bear in mind that, unlike +num, parseInt (as the name suggests) will convert a float into an integer by chopping off everything following the decimal point (if you want to use parseInt() because of this behaviour, you're probably better off using another method instead):

+'12.345'          // 12.345
parseInt(12.345)   // 12
parseInt('12.345') // 12

Empty strings

Empty strings may be a little counter-intuitive. +num converts empty strings or strings with spaces to zero, and isNaN() assumes the same:

+''                // 0
+'   '             // 0
isNaN('')          // false
isNaN('   ')       // false

But parseInt() does not agree:

parseInt('')       // NaN
parseInt('   ')    // NaN
Tanguay answered 6/10, 2008 at 19:24 Comment(33)
A very important note about parseInt is that it will allow you to specify a radix for converting the string to an int. This is a big gotcha as it tries to guess a radix for you if you don't supply it. So, for example: parseInt("17") results in 17 (decimal, 10), but parseInt("08") results in 0 (octal, 8). So, unless you intend otherwise, it is safest to use parseInt(number, 10), specifying 10 as the radix explicitly.Lithotrity
Note that !isNaN(undefined) returns false.Bomber
Downvote because isNaN also returns false with charcode 9, maybe happens with other 'strange' charcodes.Uturn
This is just plain wrong - how did it get so many upvotes? You cannot use isNaN "To check to see if a variable is not a number". "not a number" is not the same as "IEEE-794 NaN", which is what isNaN tests for. In particular, this usage fails when testing booleans and empty strings, at least. See developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/….Ursuline
Note that isNaN( true ) and isNaN( false ) will always return false! So boolean values are also numbers for this function)Zymo
The fastest possible way to check if something is a number is the "equal to self" check: var n = 'a'; if (+n === +n) { // is number } It is ~3994% faster than isNaN in the latest version of Chrome. See the performance test here: jsperf.com/isnan-vs-typeof/5Malarkey
+"string" does not reliably return NaN if non numeric characters as radix is guessed. try +"0x30"Pteryla
Actually, when checking: parseInt('') === NaN - it fails. Although, printing it in the console window: parseInt(''); // prints NaN. WeirdPacer
@Arman-Bimatov, that is because NaN !== NaN. To check to see if the result from parseInt(x) is not a number, you'd check isNaN(parseInt(x))Superstition
!isNaN(false) = true so false is a number?Ahab
@Ahab false and true can be interpreted as 0 and 1. false + true + true + false + true; equals 3 (like 0 + 1 + 1 + 0 + 1). So yes. See @Superstition 's comment, you should use !isNaN(parseInt(false)) instead, it will return falseSarchet
isNaN(' ') == false so an empty space is a valid number?!Neurovascular
@Tanguay Perhaps the isFinite function should be added to this answer. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Incarnation
"Only contains numeric characters" overstates a bit. Suggest you add an exception list: +'0xdeadbeef' === 3735928559 and +'6e4' == 60000Increase
** Warning ** This answer is wrong. Use at your own risk. Example: isNaN(1 + false + parseInt("1.do you trust your users?"))Ironing
If you use isNaN - be aware of the following dangerous arguments for which isNaN will return false: isNaN([]), isNaN([234]), isNaN(null), isNaN(true), isNaN(false), isNaN(''), isNaN(' '). The last one is a string of one or more spaces.Tibbs
Also be aware that there is a case when isNaN can end up with an exception. It happens if you are trying to apply it on a Symbol: var mySymbol = Symbol('Hey') and then isNaN(mySymbol) will throw Cannot convert a Symbol value to a number instead of returning true.Tibbs
@Tanguay can you update your answer to address the risks of using isNaN checks with empty spaces, false values, etc? Evidently this post is causing a lot of bugs.Exhort
This is wrong. !isNaN(parseInt('5aaaa')) returns true but "5aaaa" is clearly not a number.Changsha
also null value is problematic: !isNaN(12) -> true, !isNaN(null) -> trueTurpin
Note: isNaN(new Date()) return false !Jac
!isNaN(null) => trueHeliogabalus
Check this answer. It worked better than the accepted solution.Goodin
This is wrong. Moderators, please considering tagging this answer as possibly having low-quality information. For one thing, IsNaN("") returns false which clearly is incorrect. It's like saying isSandwich regarding an empty plate.Batts
@Wade Have you actually tried evaluating isNan("")? it definitely returns false, at least in Chrome. I know it's nonsensical - but that's the behaviour!Tanguay
Of course. The telltale sign that there's something off about isNaN is that no typed language would let you assign "" to a variable typed as a number (e.g. Double, Int, Float, etc.). Yet, according to IsNaN, "" is equivalent to something numerical.Batts
@Kevin Jurkowski, n => {return +n === +n} returns true for: [], [2], [undefined], '', (new Date()), true and false.Kentigera
NaN stands for Not a Number, so if Number.isNaN(x) is true, then it means that x is not a number obviously.Refinery
Testing with !isNaN(null) the result is true, and I don't expect that. so we need to add a conditional for null value if (num === null) return falseUnskillful
If confronted with a string, I'm afraid Number.isNaN() will give surprising results: $ node -i Welcome to Node.js v14.18.2. Type ".help" for more information. > Number.isNaN('hippoi') false > Number.isNaN(1) false Numbe.isNaN() regards a string a number?!?!?! Might as well just roll your own solution: val.match(/^\d+$/)Guenna
The function should check for a non-null constructor being String, rather than a typeof being string, as valid strings can be instantiated with the constructor and they will be of type object: isNumeric(new String('3')) returns false, where !isNaN(new String('3')) returns true.Gimel
What about "01" when it's intended to be a string and not have the leading 0 stripped away?Disenfranchise
Note that @KevinJurkowski's comment is unfortunately also wrong and will fail when your input is null, as +null === +null will report as true, because +null is a valid arithmetic statement in JS, and evaluates to 0 rather than NaN, so his solution only works if you've already ruled out nulls in your inputs earlier in your codepath.Inwardness
T
209

If you're just trying to check if a string is a whole number (no decimal places), regex is a good way to go. Other methods such as isNaN are too complicated for something so simple.

function isNumeric(value) {
    return /^-?\d+$/.test(value);
}

console.log(isNumeric('abcd'));         // false
console.log(isNumeric('123a'));         // false
console.log(isNumeric('1'));            // true
console.log(isNumeric('1234567890'));   // true
console.log(isNumeric('-23'));          // true
console.log(isNumeric(1234));           // true
console.log(isNumeric(1234n));          // true
console.log(isNumeric('123.4'));        // false
console.log(isNumeric(''));             // false
console.log(isNumeric(undefined));      // false
console.log(isNumeric(null));           // false

To only allow positive whole numbers use this:

function isNumeric(value) {
    return /^\d+$/.test(value);
}

console.log(isNumeric('123'));          // true
console.log(isNumeric('-23'));          // false
Tripletail answered 27/6, 2014 at 17:13 Comment(14)
console.log(isNumeric('-1'));Skyla
console.log(isNumeric('2e2'));Plum
Perhaps just rename "isNumeric" to "hasOnlyDigits". in many cases, that is exactly the check you are looking for.Vosges
This is what I was looking for, the equivalent to php ctype_digitMidtown
This might be better /^-?[0-9.,]+/ if you want to allow values like -1.5pxWhacking
Slightly better.. disallow numeric characters from languages like arabic /^[0-9]+$/.test(value)Slatternly
@dreamLo, /^-?[0-9.,]+/ but not working for this: console.log(isNumeric(',ab')); console.log(isNumeric('.ab'));Cooker
@HediHerdiana A fix for that would be /^-?[0-9]([0-9.,]+)?/. This will only allow the ., only if the first character is a digit. This regex is more for checking if the string starts as a number, for example -1.5px.Whacking
Why is this true? isNumeric(1234n) ?Cullis
it is strange to see someone providing a regex answer claiming other methods are complicatedHauptmann
@Hauptmann it's about as simple of a regex as you can get...Tripletail
@Cullis the "n" at the end I believe tells JavaScript it is a bigint.Gride
Is "0111" a number? It's a string by my book.Disenfranchise
@Disenfranchise Javascript will do a lot of behind-the-scene conversions. When I do var test = 0111 it stores 73, which is in 0111 in Octal. It's up to you to decide on the scope.Chromogen
D
92

The accepted answer for this question has quite a few flaws (as highlighted by couple of other users). This is one of the easiest & proven way to approach it in javascript:

function isNumeric(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

Below are some good test cases:

console.log(isNumeric(12345678912345678912)); // true
console.log(isNumeric('2 '));                 // true
console.log(isNumeric('-32.2 '));             // true
console.log(isNumeric(-32.2));                // true
console.log(isNumeric(undefined));            // false

// the accepted answer fails at these tests:
console.log(isNumeric(''));                   // false
console.log(isNumeric(null));                 // false
console.log(isNumeric([]));                   // false
Donoghue answered 25/10, 2018 at 9:52 Comment(6)
parseFloat is insufficient for this application because it will return a valid number parsed so far, when it encounters the first character that cannot be parsed as a number. eg. parseFloat('1.1ea10') === 1.1.Lehmbruck
beware, if you use Number.isNan and Number.isFinite, this will not work.Dr
For strings Number.isNaN and Number.isFinite won't work because they won't cast string to number.Destructionist
how about 10,1?Sycophant
this will not work with an array input isNumeric([2]). an Arraytype is not numericApplicant
!isNaN(parseFloat('0111')) && isFinite('0111') === trueDisenfranchise
C
79

And you could go the RegExp-way:

var num = "987238";

if(num.match(/^-?\d+$/)){
  //valid integer (positive or negative)
}else if(num.match(/^\d+\.\d+$/)){
  //valid float
}else{
  //not valid number
}
Cocci answered 6/10, 2008 at 19:20 Comment(9)
In this case, RegExp == badIllassorted
This fails on hexadecimal numbers (0x12, for example), floats without a leading zero (.42, for example) and negative numbers.Rossen
@JoelCoehoorn Care to elaborate on why RegExp == bad here? Seems to be a valid use case to me.Bravura
There are more ways than it seems to build a number (hex numbers in another comment are just one example), and there are many numbers that may not be considered valid (overflow the type, too precise, etc). Also, regex is both slower and more complicated than just using the built-in mechanismsIllassorted
Suggest /^-?\d+$/ and /^-?\d*\.\d+$/ e.g. "-42" and "-.42"Increase
Note that running myRegExp.test(num) is slightly more efficient than the match approach. See jsperf.com/regexp-test-search-vs-indexof/12Northeast
should also match scientific notation... 1e10 etc.Muffler
Down vote: instead of using Regex consider using JQuery's $.isNumeric. There are so many possibilities of number representations that you will most likely fail to consider all of them with a regex.Kirov
Every other answer has some sort of gotcha. This one, which limited in scope, does not seem to have any, once you accept that limited scope.Davit
N
55

If you really want to make sure that a string contains only a number, any number (integer or floating point), and exactly a number, you cannot use parseInt()/ parseFloat(), Number(), or !isNaN() by themselves. Note that !isNaN() is actually returning true when Number() would return a number, and false when it would return NaN, so I will exclude it from the rest of the discussion.

The problem with parseFloat() is that it will return a number if the string contains any number, even if the string doesn't contain only and exactly a number:

parseFloat("2016-12-31")  // returns 2016
parseFloat("1-1") // return 1
parseFloat("1.2.3") // returns 1.2

The problem with Number() is that it will return a number in cases where the passed value is not a number at all!

Number("") // returns 0
Number(" ") // returns 0
Number(" \u00A0   \t\n\r") // returns 0

The problem with rolling your own regex is that unless you create the exact regex for matching a floating point number as Javascript recognizes it you are going to miss cases or recognize cases where you shouldn't. And even if you can roll your own regex, why? There are simpler built-in ways to do it.

However, it turns out that Number() (and isNaN()) does the right thing for every case where parseFloat() returns a number when it shouldn't, and vice versa. So to find out if a string is really exactly and only a number, call both functions and see if they both return true:

function isNumber(str) {
  if (typeof str != "string") return false // we only process strings!
  // could also coerce to string: str = ""+str
  return !isNaN(str) && !isNaN(parseFloat(str))
}
Neurovascular answered 2/3, 2016 at 22:56 Comment(5)
This returns true when the string has leading or trailing spaces. ' 1', '2 ' and ' 3 ' all return true.Othilia
Adding something like this to the return-statement would solve that: && !/^\s+|\s+$/g.test(str)Sonde
@RuudLenders - most people won't care if there are trailing spaces that get lopped off to make the string a valid number, because its easy to accidentally put in the extra spaces in lots of interfaces.Necrose
That's true in case the number string is coming from user input. But I thought I should mention spaces anyway, because I think most people who need an isNumber function aren't dealing with user interfaces. Also, a good number input won't allow spaces to begin with.Othilia
@Neurovascular Thank you very much for this post. I found it tremendously helpful as I wade my way into JavaScript. In the academic arena, not a practical concern, the string "Infinity" is returned as a number (true) by the above function which makes sense because Infinity is a number in Javascript :-). Both the Numeric() and parseFloat convert the string to Infinity. Thanks, peace.Typescript
K
42

2019: Including ES3, ES6 and TypeScript Examples

Maybe this has been rehashed too many times, however I fought with this one today too and wanted to post my answer, as I didn't see any other answer that does it as simply or thoroughly:

ES3

var isNumeric = function(num){
    return (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);  
}

ES6

const isNumeric = (num) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num);

Typescript

const isNumeric = (num: any) => (typeof(num) === 'number' || typeof(num) === "string" && num.trim() !== '') && !isNaN(num as number);

This seems quite simple and covers all the bases I saw on the many other posts and thought up myself:

// Positive Cases
console.log(0, isNumeric(0) === true);
console.log(1, isNumeric(1) === true);
console.log(1234567890, isNumeric(1234567890) === true);
console.log('1234567890', isNumeric('1234567890') === true);
console.log('0', isNumeric('0') === true);
console.log('1', isNumeric('1') === true);
console.log('1.1', isNumeric('1.1') === true);
console.log('-1', isNumeric('-1') === true);
console.log('-1.2354', isNumeric('-1.2354') === true);
console.log('-1234567890', isNumeric('-1234567890') === true);
console.log(-1, isNumeric(-1) === true);
console.log(-32.1, isNumeric(-32.1) === true);
console.log('0x1', isNumeric('0x1') === true);  // Valid number in hex
// Negative Cases
console.log(true, isNumeric(true) === false);
console.log(false, isNumeric(false) === false);
console.log('1..1', isNumeric('1..1') === false);
console.log('1,1', isNumeric('1,1') === false);
console.log('-32.1.12', isNumeric('-32.1.12') === false);
console.log('[blank]', isNumeric('') === false);
console.log('[spaces]', isNumeric('   ') === false);
console.log('null', isNumeric(null) === false);
console.log('undefined', isNumeric(undefined) === false);
console.log([], isNumeric([]) === false);
console.log('NaN', isNumeric(NaN) === false);

You can also try your own isNumeric function and just past in these use cases and scan for "true" for all of them.

Or, to see the values that each return:

Results of each test against <code>isNumeric()</code>

Kevon answered 24/10, 2019 at 22:50 Comment(6)
good, except for example for '0x10' (returns true!)Campaign
@S.Serpooshan, 0x10 should return true, it is a hex number. 0x1 is shown in the test cases and and is expected to return true, it is a number. If your specific use case requires that hex numbers be treated as a string then you will need to write the solution a little differently.Kevon
Yes, it depends on our scenarioCampaign
Also works with scientific notation: isNumeric('3e2') / isNumeric(3e2)Jarmon
The type for the typescript version should be unknown: const isNumeric = (num: unknown)Gnarly
(typeof('0111') === 'number' || typeof('0111') === "string" && '0111'.trim() !== '') && !isNaN('0111'); Thus data is lost. Namely the intended zero prefix.Disenfranchise
E
35

TL;DR

It depends largely on what you want to parse as a number.

Comparison Between Built-in Functions

As none of the existing sources satisfied my soul, I tried to figure out what actually was happening with these functions.

Three immediate answers to this question felt like:

  1. !isNaN(input) (which gives the same output as +input === +input)
  2. !isNaN(parseFloat(input))
  3. isFinite(input)

But are any of them correct in every scenario?

I tested these functions in several cases, and generated output as markdown. This is what it looks like:

input !isNaN(input) or
+input===+input
!isNaN(
parseFloat(
input))
isFinite(
input)
Comment
123 ✔️ ✔️ ✔️ -
'123' ✔️ ✔️ ✔️ -
12.3 ✔️ ✔️ ✔️ -
'12.3' ✔️ ✔️ ✔️ -
'   12.3   ' ✔️ ✔️ ✔️ Empty whitespace trimmed, as expected.
1_000_000 ✔️ ✔️ ✔️ Numeric separator understood, also expected.
'1_000_000' ✔️ Surprise! JS just won't parse numeric separator inside a string. For details, check this issue. (Why then parsing as float worked though? Well, it didn't. 😉)
'0b11111111' ✔️ ✔️ ✔️ Binary form understood, as it should've.
'0o377' ✔️ ✔️ ✔️ Octal form understood too.
'0xFF' ✔️ ✔️ ✔️ Of course hex is understood. Did anybody think otherwise? 😒
'' ✔️ ✔️ Should empty string be a number?
'    ' ✔️ ✔️ Should a whitespace-only string be a number?
'abc' Everybody agrees, not a number.
'12.34Ab!@#$' ✔️ Ah! Now it's quite understandable what parseFloat() does. Not impressive to me, but may come handy in certain cases.
'10e100' ✔️ ✔️ ✔️ 10100 is a number indeed.
But caution! It's way more larger than the maximum safe integer value 253 (about 9×1015). Read this for details.
'10e1000' ✔️ ✔️ Say with me, help!
Though not as crazy as it may seem. In JavaScript, a value larger than ~10308 is rounded to infinity, that's why. Look here for details.
And yes, isNaN() considers infinity as a number, and parseFloat() parses infinity as infinity.
null ✔️ ✔️ Now this is awkward. In JS, when a conversion is needed, null becomes zero, and we get a finite number.
Then why parseFloat(null) should return a NaN here? Someone please explain this design concept to me.
undefined As expected.
Infinity ✔️ ✔️ As explained before, isNaN() considers infinity as a number, and parseFloat() parses infinity as infinity.

So...which of them is "correct"?

Should be clear by now, it depends largely on what we need. For example, we may want to consider a null input as 0. In that case isFinite() will work fine.

Again, perhaps we will take a little help from isNaN() when 1010000000000 is needed to be considered a valid number (although the question remains—why would it be, and how would we handle that)!

Of course, we can manually exclude any of the scenarios.

Like in my case, I needed exactly the outputs of isFinite(), except for the null case, the empty string case, and the whitespace-only string case. Also I had no headache about really huge numbers. So my code looked like this:

/**
 * My necessity was met by the following code.
 */

if (input === null) {
    // Null input
} else if (input.trim() === '') {
    // Empty or whitespace-only string
} else if (isFinite(input)) {
    // Input is a number
} else {
    // Not a number
}

And also, this was my JavaScript to generate the table:

/**
 * Note: JavaScript does not print numeric separator inside a number.
 * In that single case, the markdown output was manually corrected.
 * Also, the comments were manually added later, of course.
 */

let inputs = [
    123, '123', 12.3, '12.3', '   12.3   ',
    1_000_000, '1_000_000',
    '0b11111111', '0o377', '0xFF',
    '', '    ',
    'abc', '12.34Ab!@#$',
    '10e100', '10e1000',
    null, undefined, Infinity];

let markdownOutput = `| \`input\` | \`!isNaN(input)\` or <br>\`+input === +input\` | \`!isNaN(parseFloat(input))\` | \`isFinite(input)\` | Comment |
| :---: | :---: | :---: | :---: | :--- |\n`;

for (let input of inputs) {
    let outputs = [];
    outputs.push(!isNaN(input));
    outputs.push(!isNaN(parseFloat(input)));
    outputs.push(isFinite(input));

    if (typeof input === 'string') {
        // Output with quotations
        console.log(`'${input}'`);
        markdownOutput += `| '${input}'`;
    } else {
        // Output without quotes
        console.log(input);
        markdownOutput += `| ${input}`;
    }

    for (let output of outputs) {
        console.log('\t' + output);
        if (output === true) {
            markdownOutput += ` | <div style="color:limegreen">true</div>`;
            // markdownOutput += ` | ✔️`; // for stackoverflow
        } else {
            markdownOutput += ` | <div style="color:orangered">false</div>`;
            // markdownOutput += ` | ❌`; // for stackoverflow
        }
    }

    markdownOutput += ` ||\n`;
}

// Replace two or more whitespaces with $nbsp;
markdownOutput = markdownOutput.replaceAll(`  `, `&nbsp;&nbsp;`);

// Print markdown to console
console.log(markdownOutput);
Epa answered 17/8, 2021 at 17:2 Comment(3)
And a more rigorous solutionPatency
Excellent answer. Kudos.Wight
'0123' A string which is expected to remain a string but any of these technique detect a number and will result in the 0 being lost.Disenfranchise
A
31

Try the isNan function:

The isNaN() function determines whether a value is an illegal number (Not-a-Number).

This function returns true if the value equates to NaN. Otherwise it returns false.

This function is different from the Number specific Number.isNaN() method.

  The global isNaN() function, converts the tested value to a Number, then tests it.

Number.isNan() does not convert the values to a Number, and will not return true for any value that is not of the type Number...

Apiece answered 6/10, 2008 at 19:14 Comment(5)
Make sure you add a check for the empty string. isNaN('') returns false but you probably want it to return true in this case.Spatola
isFinite is a better check - it deals with the wierd corner case of InfinityTouchwood
@MichaelHaren Not good enough! isNaN() returns false for ANY string containing only whitespace characters, including things like '\u00A0'.Neurovascular
WARNING: Does not work for the values: null, "" (empty string) and false.Fathead
I realize this answer was given 11 years ago and a few minutes before the accepted one, but like it or not, the accepted answer has WAY more conversation around it, so this answer doesn't really add anything to answering the question. I would kindly suggest deleting it, to avoid distracting new readers. I also think you'll get the Disciplined badge if you do that.Meagher
M
28

The JavaScript global isFinite() checks if a value is a valid (finite) number.

See MDN for the difference between Number.isFinite() and global isFinite().

let a = isFinite('abc') // false
let b = isFinite('123') // true
let c = isFinite('12a') // false
let d = isFinite(null)  // true
console.log(a, b, c, d)
Meda answered 27/6, 2022 at 10:44 Comment(3)
isFinite(null) returns true!Wolfie
@Harry, according to Mozilla Docs, using Number.isFinite(null) would be more robust and would return false. Downside is if you want to accept '0' as this would also return false. Seems best to first reject null and then use isFinite if one wants to use this.Intended
Also take care isFinite([]) and isFinite('') returns trueMotheaten
L
19

Old question, but there are several points missing in the given answers.

Scientific notation.

!isNaN('1e+30') is true, however in most of the cases when people ask for numbers, they do not want to match things like 1e+30.

Large floating numbers may behave weird

Observe (using Node.js):

> var s = Array(16 + 1).join('9')
undefined
> s.length
16
> s
'9999999999999999'
> !isNaN(s)
true
> Number(s)
10000000000000000
> String(Number(s)) === s
false
>

On the other hand:

> var s = Array(16 + 1).join('1')
undefined
> String(Number(s)) === s
true
> var s = Array(15 + 1).join('9')
undefined
> String(Number(s)) === s
true
>

So, if one expects String(Number(s)) === s, then better limit your strings to 15 digits at most (after omitting leading zeros).

Infinity

> typeof Infinity
'number'
> !isNaN('Infinity')
true
> isFinite('Infinity')
false
>

Given all that, checking that the given string is a number satisfying all of the following:

  • non scientific notation
  • predictable conversion to Number and back to String
  • finite

is not such an easy task. Here is a simple version:

  function isNonScientificNumberString(o) {
    if (!o || typeof o !== 'string') {
      // Should not be given anything but strings.
      return false;
    }
    return o.length <= 15 && o.indexOf('e+') < 0 && o.indexOf('E+') < 0 && !isNaN(o) && isFinite(o);
  }

However, even this one is far from complete. Leading zeros are not handled here, but they do screw the length test.

Lan answered 2/10, 2013 at 11:28 Comment(1)
"however in most of the cases when people ask for numbers, they do not want to match things like 1e+30" Why would you say this? If someone wants to know if a string contains a number, it seems to me that they would want to know if it contains a number, and 1e+30 is a number. Certainly if I were testing a string for a numeric value in JavaScript, I would want that to match.Diocletian
N
18

Someone may also benefit from a regex based answer. Here it is:

One liner isInteger:

const isInteger = num => /^-?[0-9]+$/.test(num+'');

One liner isNumeric: Accepts integers and decimals

const isNumeric = num => /^-?[0-9]+(?:\.[0-9]+)?$/.test(num+'');
Novokuznetsk answered 19/12, 2021 at 3:33 Comment(4)
This has the issue of considering whitespace to be an invalid character, if that's not what you want then rather use const isInteger = num => /^\s*-?[0-9]+\s*$/.test(num+''); or const isNumeric = num => /^\s*-?[0-9]+(?:\.[0-9]+)\s*?$/.test(num+'');Litmus
@yoelhalb Whitespace is an invalid character for a number. You can trim the string before you pass it in.Novokuznetsk
empty string isn't a number. But i guess that's true ;)Meraree
This also doesn't account for other ways to format numbers, e.g., hex numbers and scientific notation.Passover
L
17

I have tested and Michael's solution is best. Vote for his answer above (search this page for "If you really want to make sure that a string" to find it). In essence, his answer is this:

function isNumeric(num){
  num = "" + num; //coerce num to be a string
  return !isNaN(num) && !isNaN(parseFloat(num));
}

It works for every test case, which I documented here: https://jsfiddle.net/wggehvp9/5/

Many of the other solutions fail for these edge cases: ' ', null, "", true, and []. In theory, you could use them, with proper error handling, for example:

return !isNaN(num);

or

return (+num === +num);

with special handling for /\s/, null, "", true, false, [] (and others?)

Lomalomas answered 21/2, 2017 at 0:0 Comment(2)
This still returns true with trailing/leading spaces. Adding something like this to the return-statement would solve that: && !/^\s+|\s+$/g.test(str)Sonde
So ' 123' should be false, not a number, while '1234' should be a number? I like how it is, so that " 123" is a number, but that may be up to the discretion of the developer if leading or trailing spaces should change the value.Lomalomas
S
13

You can use the result of Number when passing an argument to its constructor.

If the argument (a string) cannot be converted into a number, it returns NaN, so you can determinate if the string provided was a valid number or not.

Notes: Note when passing empty string or '\t\t' and '\n\t' as Number will return 0; Passing true will return 1 and false returns 0.

    Number('34.00') // 34
    Number('-34') // -34
    Number('123e5') // 12300000
    Number('123e-5') // 0.00123
    Number('999999999999') // 999999999999
    Number('9999999999999999') // 10000000000000000 (integer accuracy up to 15 digit)
    Number('0xFF') // 255
    Number('Infinity') // Infinity  

    Number('34px') // NaN
    Number('xyz') // NaN
    Number('true') // NaN
    Number('false') // NaN

    // cavets
    Number('    ') // 0
    Number('\t\t') // 0
    Number('\n\t') // 0
Staid answered 13/3, 2015 at 9:31 Comment(2)
The Number constructor is exactly the same as +x.Capercaillie
As a side note, keep in mind that the ES6 Number() handles float numbers as well, like Number.parseFloat() not Number.parseInt()Superheterodyne
D
11

Maybe there are one or two people coming across this question who need a much stricter check than usual (like I did). In that case, this might be useful:

if(str === String(Number(str))) {
  // it's a "perfectly formatted" number
}

Beware! This will reject strings like .1, 40.000, 080, 00.1. It's very picky - the string must match the "most minimal perfect form" of the number for this test to pass.

It uses the String and Number constructor to cast the string to a number and back again and thus checks if the JavaScript engine's "perfect minimal form" (the one it got converted to with the initial Number constructor) matches the original string.

Diarthrosis answered 9/1, 2017 at 10:57 Comment(4)
Thanks @JoeRocc. I needed this too, but just for integers, so I added: (str === String(Math.round(Number(str)))).Ironing
Be aware that "Infinity", "-Infinity", and "NaN" pass this test. However, this can be fixed using an additional Number.isFinite test.Capercaillie
This is exactly the same as str === ("" + +str). It basically checks whether the string is the result of stringifying a JS number. Knowing this, we can also see a problem: the test passes for 0.000001 but fails for 0.0000001, which is when 1e-7 passes instead. The same for very big numbers.Capercaillie
This answer is incorrect. 1e10 is "perfectly valid and formatted", and yet fails this algorithm.Lehmbruck
S
8

Why is jQuery's implementation not good enough?

function isNumeric(a) {
    var b = a && a.toString();
    return !$.isArray(a) && b - parseFloat(b) + 1 >= 0;
};

Michael suggested something like this (although I've stolen "user1691651 - John"'s altered version here):

function isNumeric(num){
    num = "" + num; //coerce num to be a string
    return !isNaN(num) && !isNaN(parseFloat(num));
}

The following is a solution with most likely bad performance, but solid results. It is a contraption made from the jQuery 1.12.4 implementation and Michael's answer, with an extra check for leading/trailing spaces (because Michael's version returns true for numerics with leading/trailing spaces):

function isNumeric(a) {
    var str = a + "";
    var b = a && a.toString();
    return !$.isArray(a) && b - parseFloat(b) + 1 >= 0 &&
           !/^\s+|\s+$/g.test(str) &&
           !isNaN(str) && !isNaN(parseFloat(str));
};

The latter version has two new variables, though. One could get around one of those, by doing:

function isNumeric(a) {
    if ($.isArray(a)) return false;
    var b = a && a.toString();
    a = a + "";
    return b - parseFloat(b) + 1 >= 0 &&
            !/^\s+|\s+$/g.test(a) &&
            !isNaN(a) && !isNaN(parseFloat(a));
};

I haven't tested any of these very much, by other means than manually testing the few use-cases I'll be hitting with my current predicament, which is all very standard stuff. This is a "standing-on-the-shoulders-of-giants" situation.

Sonde answered 15/5, 2017 at 12:39 Comment(0)
A
8

I like the simplicity of this.

Number.isNaN(Number(value))

The above is regular Javascript, but I'm using this in conjunction with a typescript typeguard for smart type checking. This is very useful for the typescript compiler to give you correct intellisense, and no type errors.

Typescript typeguards

Warning: See Jeremy's comment below. This has some issues with certain values and I don't have time to fix it now, but the idea of using a typescript typeguard is useful so I won't delete this section.

isNotNumber(value: string | number): value is string {
    return Number.isNaN(Number(this.smartImageWidth));
}
isNumber(value: string | number): value is number {
    return Number.isNaN(Number(this.smartImageWidth)) === false;
}

Let's say you have a property width which is number | string. You may want to do logic based on whether or not it's a string.

var width: number|string;
width = "100vw";

if (isNotNumber(width)) 
{
    // the compiler knows that width here must be a string
    if (width.endsWith('vw')) 
    {
        // we have a 'width' such as 100vw
    } 
}
else 
{
    // the compiler is smart and knows width here must be number
    var doubleWidth = width * 2;    
}

The typeguard is smart enough to constrain the type of width within the if statement to be ONLY string. This permits the compiler to allow width.endsWith(...) which it wouldn't allow if the type was string | number.

You can call the typeguard whatever you want isNotNumber, isNumber, isString, isNotString but I think isString is kind of ambiguous and harder to read.

Alvaalvan answered 27/6, 2018 at 7:30 Comment(2)
Works relatively well in plain JS, but fails cases like 1..1, 1,1, -32.1.12, and more importantly fails undefined and NaN. Not sure if your TS makes up for it, but it looks like if you passed undefined or a NaN that it would fail trying to do undefined * 2, which won't crash but will return NaN.Kevon
Note that this approach allows an e or E in the number (for instance 2E34) as it is considered a valid number (the "scientific notation"), but is not necessarily what you want...Litmus
E
8

2019: Practical and tight numerical validity check

Often, a 'valid number' means a Javascript number excluding NaN and Infinity, ie a 'finite number'.

To check the numerical validity of a value (from an external source for example), you can define in ESlint Airbnb style :

/**
 * Returns true if 'candidate' is a finite number or a string referring (not just 'including') a finite number
 * To keep in mind:
 *   Number(true) = 1
 *   Number('') = 0
 *   Number("   10  ") = 10
 *   !isNaN(true) = true
 *   parseFloat('10 a') = 10
 *
 * @param {?} candidate
 * @return {boolean}
 */
function isReferringFiniteNumber(candidate) {
  if (typeof (candidate) === 'number') return Number.isFinite(candidate);
  if (typeof (candidate) === 'string') {
    return (candidate.trim() !== '') && Number.isFinite(Number(candidate));
  }
  return false;
}

and use it this way:

if (isReferringFiniteNumber(theirValue)) {
  myCheckedValue = Number(theirValue);
} else {
  console.warn('The provided value doesn\'t refer to a finite number');
}
Ecdysiast answered 14/11, 2019 at 5:5 Comment(0)
B
7

It is not valid for TypeScript as:

declare function isNaN(number: number): boolean;

For TypeScript you can use:

/^\d+$/.test(key)

Basil answered 23/5, 2019 at 13:55 Comment(1)
/^\d+$/.test("-1") // false To use isNaN with non-numbers in TS, you can just cast the value to any, or use one of the other more comprehensive solutions here that make use of Number, parseFloat, etc.Bohlin
C
6

parseInt(), but be aware that this function is a bit different in the sense that it for example returns 100 for parseInt("100px").

Candelabrum answered 6/10, 2008 at 19:16 Comment(3)
And 11 for parseInt(09).Delineation
because you need to use paraseInt(09, 10)Tripletail
As of ECMAScript 5, which has wide browser support (IE≥9), you don't need the , 10 argument any more. parseInt('09') now equals 9.Cahier
C
6

Quote:

isNaN(num) // returns true if the variable does NOT contain a valid number

is not entirely true if you need to check for leading/trailing spaces - for example when a certain quantity of digits is required, and you need to get, say, '1111' and not ' 111' or '111 ' for perhaps a PIN input.

Better to use:

var num = /^\d+$/.test(num)
Consolidate answered 1/6, 2012 at 5:31 Comment(1)
The values '-1', '0.1' and '1e10' all return false. Furthermore, values larger than positive infinity or smaller than negative infinity return true, while they probably should return false.Othilia
E
6

When guarding against empty strings and null

// Base cases that are handled properly
Number.isNaN(Number('1')); // => false
Number.isNaN(Number('-1')); // => false
Number.isNaN(Number('1.1')); // => false
Number.isNaN(Number('-1.1')); // => false
Number.isNaN(Number('asdf')); // => true
Number.isNaN(Number(undefined)); // => true

// Special notation cases that are handled properly
Number.isNaN(Number('1e1')); // => false
Number.isNaN(Number('1e-1')); // => false
Number.isNaN(Number('-1e1')); // => false
Number.isNaN(Number('-1e-1')); // => false
Number.isNaN(Number('0b1')); // => false
Number.isNaN(Number('0o1')); // => false
Number.isNaN(Number('0xa')); // => false

// Edge cases that will FAIL if not guarded against
Number.isNaN(Number('')); // => false
Number.isNaN(Number(' ')); // => false
Number.isNaN(Number(null)); // => false

// Edge cases that are debatable
Number.isNaN(Number('-0b1')); // => true
Number.isNaN(Number('-0o1')); // => true
Number.isNaN(Number('-0xa')); // => true
Number.isNaN(Number('Infinity')); // => false 
Number.isNaN(Number('INFINITY')); // => true  
Number.isNaN(Number('-Infinity')); // => false 
Number.isNaN(Number('-INFINITY')); // => true  

When NOT guarding against empty strings and null

Using parseInt:

// Base cases that are handled properly
Number.isNaN(parseInt('1')); // => false
Number.isNaN(parseInt('-1')); // => false
Number.isNaN(parseInt('1.1')); // => false
Number.isNaN(parseInt('-1.1')); // => false
Number.isNaN(parseInt('asdf')); // => true
Number.isNaN(parseInt(undefined)); // => true
Number.isNaN(parseInt('')); // => true
Number.isNaN(parseInt(' ')); // => true
Number.isNaN(parseInt(null)); // => true

// Special notation cases that are handled properly
Number.isNaN(parseInt('1e1')); // => false
Number.isNaN(parseInt('1e-1')); // => false
Number.isNaN(parseInt('-1e1')); // => false
Number.isNaN(parseInt('-1e-1')); // => false
Number.isNaN(parseInt('0b1')); // => false
Number.isNaN(parseInt('0o1')); // => false
Number.isNaN(parseInt('0xa')); // => false

// Edge cases that are debatable
Number.isNaN(parseInt('-0b1')); // => false
Number.isNaN(parseInt('-0o1')); // => false
Number.isNaN(parseInt('-0xa')); // => false
Number.isNaN(parseInt('Infinity')); // => true 
Number.isNaN(parseInt('INFINITY')); // => true  
Number.isNaN(parseInt('-Infinity')); // => true 
Number.isNaN(parseInt('-INFINITY')); // => true 

Using parseFloat:

// Base cases that are handled properly
Number.isNaN(parseFloat('1')); // => false
Number.isNaN(parseFloat('-1')); // => false
Number.isNaN(parseFloat('1.1')); // => false
Number.isNaN(parseFloat('-1.1')); // => false
Number.isNaN(parseFloat('asdf')); // => true
Number.isNaN(parseFloat(undefined)); // => true
Number.isNaN(parseFloat('')); // => true
Number.isNaN(parseFloat(' ')); // => true
Number.isNaN(parseFloat(null)); // => true

// Special notation cases that are handled properly
Number.isNaN(parseFloat('1e1')); // => false
Number.isNaN(parseFloat('1e-1')); // => false
Number.isNaN(parseFloat('-1e1')); // => false
Number.isNaN(parseFloat('-1e-1')); // => false
Number.isNaN(parseFloat('0b1')); // => false
Number.isNaN(parseFloat('0o1')); // => false
Number.isNaN(parseFloat('0xa')); // => false

// Edge cases that are debatable
Number.isNaN(parseFloat('-0b1')); // => false
Number.isNaN(parseFloat('-0o1')); // => false
Number.isNaN(parseFloat('-0xa')); // => false
Number.isNaN(parseFloat('Infinity')); // => false 
Number.isNaN(parseFloat('INFINITY')); // => true  
Number.isNaN(parseFloat('-Infinity')); // => false 
Number.isNaN(parseFloat('-INFINITY')); // => true

Notes:

  • Only string, empty, and uninitialized values are considered in keeping with addressing the original question. Additional edge cases exist if arrays and objects are the values being considered.
  • Characters in binary, octal, hexadecimal, and exponential notation are not case-sensitive (ie: '0xFF', '0XFF', '0xfF' etc. will all yield the same result in the test cases shown above).
  • Unlike with Infinity (case-sensitive) in some cases, constants from the Number and Math objects passed as test cases in string format to any of the methods above will be determined to not be numbers.
  • See here for an explanation of how arguments are converted to a Number and why the edge cases for null and empty strings exist.
Earleenearlene answered 17/3, 2019 at 7:24 Comment(3)
See also #46678274Felic
fails "", null, undefined andMetheglin
@Metheglin thanks for pointing out the edge cases. I updated the answer to address the ones you mentioned as well as Infinity and "Infinity". It also looks like undefined is already handled properly but I added it explicitly to make it clear.Earleenearlene
J
6

This way it works for me.

function isNumeric(num){
    let value1 = num.toString();
    let value2 = parseFloat(num).toString();
    return (value1 === value2);
}

console.log(
    isNumeric(123),     //true
    isNumeric(-123),    //true
    isNumeric('123'),   //true
    isNumeric('-123'),  //true
    isNumeric(12.2),    //true
    isNumeric(-12.2),   //true
    isNumeric('12.2'),  //true
    isNumeric('-12.2'), //true
    isNumeric('a123'),  //false
    isNumeric('123a'),  //false
    isNumeric(' 123'),  //false
    isNumeric('123 '),  //false
    isNumeric('a12.2'), //false
    isNumeric('12.2a'), //false
    isNumeric(' 12.2'), //false
    isNumeric('12.2 '), //false
)
Jemadar answered 21/11, 2021 at 6:48 Comment(0)
C
4

This is built on some of the previous answers and comments. It covers all the edge cases and also handles scientific notation optionally:

const NUMBER_REG_EXP = /^-?\d+(?:\.\d+)?$/;
const SCIENTIFIC_NOTATION_REG_EXP = /^-?\d+(?:\.\d+)?(?:[eE]\d+)?$/;

const isNumeric = (n, allowScientificNotation = false) => (
    (typeof n === 'number' && !Number.isNaN(n)) || 
    (typeof n === 'string' && (allowScientificNotation ?
        SCIENTIFIC_NOTATION_REG_EXP : NUMBER_REG_EXP).test(n))
);
Collette answered 2/4, 2020 at 11:21 Comment(0)
A
3

If anyone ever gets this far down, I spent some time hacking on this trying to patch moment.js (https://github.com/moment/moment). Here's something that I took away from it:

function isNumeric(val) {
    var _val = +val;
    return (val !== val + 1) //infinity check
        && (_val === +val) //Cute coercion check
        && (typeof val !== 'object') //Array/object check
}

Handles the following cases:

True! :

isNumeric("1"))
isNumeric(1e10))
isNumeric(1E10))
isNumeric(+"6e4"))
isNumeric("1.2222"))
isNumeric("-1.2222"))
isNumeric("-1.222200000000000000"))
isNumeric("1.222200000000000000"))
isNumeric(1))
isNumeric(0))
isNumeric(-0))
isNumeric(1010010293029))
isNumeric(1.100393830000))
isNumeric(Math.LN2))
isNumeric(Math.PI))
isNumeric(5e10))

False! :

isNumeric(NaN))
isNumeric(Infinity))
isNumeric(-Infinity))
isNumeric())
isNumeric(undefined))
isNumeric('[1,2,3]'))
isNumeric({a:1,b:2}))
isNumeric(null))
isNumeric([1]))
isNumeric(new Date()))

Ironically, the one I am struggling with the most:

isNumeric(new Number(1)) => false

Any suggestions welcome. :]

Anabolite answered 4/1, 2017 at 7:37 Comment(2)
What about isNumeric(' ') and isNumeric('')?Renaldorenard
I would add && (val.replace(/\s/g,'') !== '') //Empty && (val.slice(-1) !== '.') //Decimal without Number in order to adress the above mentioned issue and one I had myself.Meat
B
3

I recently wrote an article about ways to ensure a variable is a valid number: https://github.com/jehugaleahsa/artifacts/blob/master/2018/typescript_num_hack.md The article explains how to ensure floating point or integer, if that's important (+x vs ~~x).

The article assumes the variable is a string or a number to begin with and trim is available/polyfilled. It wouldn't be hard to extend it to handle other types, as well. Here's the meat of it:

// Check for a valid float
if (x == null
    || ("" + x).trim() === ""
    || isNaN(+x)) {
    return false;  // not a float
}

// Check for a valid integer
if (x == null
    || ("" + x).trim() === ""
    || ~~x !== +x) {
    return false;  // not an integer
}
Bountiful answered 8/10, 2018 at 21:38 Comment(0)
L
3

Save yourself the headache of trying to find a "built-in" solution.

There isn't a good answer, and the hugely upvoted answer in this thread is wrong.

npm install is-number

In JavaScript, it's not always as straightforward as it should be to reliably check if a value is a number. It's common for devs to use +, -, or Number() to cast a string value to a number (for example, when values are returned from user input, regex matches, parsers, etc). But there are many non-intuitive edge cases that yield unexpected results:

console.log(+[]); //=> 0
console.log(+''); //=> 0
console.log(+'   '); //=> 0
console.log(typeof NaN); //=> 'number'
Lily answered 20/12, 2018 at 20:25 Comment(0)
F
3
function isNumberCandidate(s) {
  const str = (''+ s).trim();
  if (str.length === 0) return false;
  return !isNaN(+str);
}

console.log(isNumberCandidate('1'));       // true
console.log(isNumberCandidate('a'));       // false
console.log(isNumberCandidate('000'));     // true
console.log(isNumberCandidate('1a'));      // false 
console.log(isNumberCandidate('1e'));      // false
console.log(isNumberCandidate('1e-1'));    // true
console.log(isNumberCandidate('123.3'));   // true
console.log(isNumberCandidate(''));        // false
console.log(isNumberCandidate(' '));       // false
console.log(isNumberCandidate(1));         // true
console.log(isNumberCandidate(0));         // true
console.log(isNumberCandidate(NaN));       // false
console.log(isNumberCandidate(undefined)); // false
console.log(isNumberCandidate(null));      // false
console.log(isNumberCandidate(-1));        // true
console.log(isNumberCandidate('-1'));      // true
console.log(isNumberCandidate('-1.2'));    // true
console.log(isNumberCandidate(0.0000001)); // true
console.log(isNumberCandidate('0.0000001')); // true
console.log(isNumberCandidate(Infinity));    // true
console.log(isNumberCandidate(-Infinity));    // true

console.log(isNumberCandidate('Infinity'));  // true

if (isNumberCandidate(s)) {
  // use +s as a number
  +s ...
}
Frumpy answered 30/1, 2019 at 13:52 Comment(0)
S
3

So, it will depend on the test cases that you want it to handle.

function isNumeric(number) {
  return !isNaN(parseFloat(number)) && !isNaN(+number);
}

What I was looking for was regular types of numbers in javascript. 0, 1 , -1, 1.1 , -1.1 , 1E1 , -1E1 , 1e1 , -1e1, 0.1e10, -0.1.e10 , 0xAF1 , 0o172, Math.PI, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY

And also they're representations as strings:
'0', '1', '-1', '1.1', '-1.1', '1E1', '-1E1', '1e1', '-1e1', '0.1e10', '-0.1.e10', '0xAF1', '0o172'

I did want to leave out and not mark them as numeric '', ' ', [], {}, null, undefined, NaN

As of today, all other answers seemed to failed one of these test cases.

Schizophrenia answered 20/10, 2020 at 1:7 Comment(1)
Note that isNumeric('007') returns true in case that matters to youToast
S
2

Well, I'm using this one I made...

It's been working so far:

function checkNumber(value) {
    return value % 1 == 0;
}

If you spot any problem with it, tell me, please.

Stoner answered 19/3, 2012 at 18:56 Comment(5)
This gives the wrong result for the empty string, empty array, false, and null.Rossen
Shouldn't it be a triple equal?Applesauce
In my application we are only allowing a-z A-Z and 0-9 characters. I found the above worked unless the string began with 0xnn and then it would return it as numeric when it shouldn't have.I've posted in a comment below so the formatting is intact.Balloon
you could just do 'return value % 1 === 0'Tilburg
Just do return !isNaN(parseInt(value, 10));Crossbill
S
2

PFB the working solution:

 function(check){ 
    check = check + "";
    var isNumber =   check.trim().length>0? !isNaN(check):false;
    return isNumber;
    }
Streaky answered 30/4, 2014 at 13:32 Comment(0)
K
2

This appears to catch the seemingly infinite number of edge cases:

function isNumber(x, noStr) {
    /*

        - Returns true if x is either a finite number type or a string containing only a number
        - If empty string supplied, fall back to explicit false
        - Pass true for noStr to return false when typeof x is "string", off by default

        isNumber(); // false
        isNumber([]); // false
        isNumber([1]); // false
        isNumber([1,2]); // false
        isNumber(''); // false
        isNumber(null); // false
        isNumber({}); // false
        isNumber(true); // false
        isNumber('true'); // false
        isNumber('false'); // false
        isNumber('123asdf'); // false
        isNumber('123.asdf'); // false
        isNumber(undefined); // false
        isNumber(Number.POSITIVE_INFINITY); // false
        isNumber(Number.NEGATIVE_INFINITY); // false
        isNumber('Infinity'); // false
        isNumber('-Infinity'); // false
        isNumber(Number.NaN); // false
        isNumber(new Date('December 17, 1995 03:24:00')); // false
        isNumber(0); // true
        isNumber('0'); // true
        isNumber(123); // true
        isNumber(123.456); // true
        isNumber(-123.456); // true
        isNumber(-.123456); // true
        isNumber('123'); // true
        isNumber('123.456'); // true
        isNumber('.123'); // true
        isNumber(.123); // true
        isNumber(Number.MAX_SAFE_INTEGER); // true
        isNumber(Number.MAX_VALUE); // true
        isNumber(Number.MIN_VALUE); // true
        isNumber(new Number(123)); // true
    */

    return (
        (typeof x === 'number' || x instanceof Number || (!noStr && x && typeof x === 'string' && !isNaN(x))) &&
        isFinite(x)
    ) || false;
};
Kristalkristan answered 8/4, 2020 at 18:57 Comment(0)
V
2

I used this function as a form validation tool, and I didn't want users to be able to write exponential function, so I came up with this function:

<script>

    function isNumber(value, acceptScientificNotation) {

        if(true !== acceptScientificNotation){
            return /^-{0,1}\d+(\.\d+)?$/.test(value);
        }

        if (true === Array.isArray(value)) {
            return false;
        }
        return !isNaN(parseInt(value, 10));
    }


    console.log(isNumber(""));              // false
    console.log(isNumber(false));           // false
    console.log(isNumber(true));            // false
    console.log(isNumber("0"));             // true
    console.log(isNumber("0.1"));           // true
    console.log(isNumber("12"));            // true
    console.log(isNumber("-12"));           // true
    console.log(isNumber(-45));             // true
    console.log(isNumber({jo: "pi"}));      // false
    console.log(isNumber([]));              // false
    console.log(isNumber([78, 79]));        // false
    console.log(isNumber(NaN));             // false
    console.log(isNumber(Infinity));        // false
    console.log(isNumber(undefined));       // false
    console.log(isNumber("0,1"));           // false



    console.log(isNumber("1e-1"));          // false
    console.log(isNumber("1e-1", true));    // true
</script>
Vally answered 11/8, 2020 at 9:33 Comment(0)
T
2

Checking the number in JS:

  1. Best way for check if it's a number:

    isFinite(20)
    //True
    
  2. Read a value out of a string. CSS *:

    parseInt('2.5rem')
    //2
    parseFloat('2.5rem')
    //2.5  
    
  3. For an integer:

    isInteger(23 / 0)
    //False
    
  4. If value is NaN:

    isNaN(20)
    //False
    
Tern answered 26/4, 2021 at 12:31 Comment(1)
What about a BigInt? Better to write Infinity rather than dividing by zero for readability but maybe that's me.Khan
G
2

This is a possible way to check whether a variable is NOT numerical:

(isNaN(foo) || ((foo !== 0) && (!foo)))

Which means that foo is either falsy but different from 0 or isNaN(foo) is true.

Another way to perform such a check is

!isNaN(parseFloat(foo))
Galbreath answered 1/7, 2022 at 15:12 Comment(0)
M
2

You can also use a simple parseInt function too... with an if the condition for example

if (parseInt(i)){
    (i in dic) ? dic[i] += 1 : dic[i] = 1
}
Montane answered 25/1, 2023 at 5:34 Comment(0)
H
2

This function gets a string and returns a boolean as a result :

const isNumber = (str) => typeof str === 'string' && str.length > 0 && !isNaN(Number(str))
Hartwell answered 1/5, 2023 at 16:46 Comment(0)
M
2
function isValidNumber(str) {
    return !isNaN(str);
}

// Example usage:
console.log(isValidNumber("123"));   // Output: true
console.log(isValidNumber("abc"));   // Output: false
console.log(isValidNumber("12.34")); // Output: true
console.log(isValidNumber(""));      // Output: false

here's an example using Number.isNaN():

function isValidNumber(str) {
    return !Number.isNaN(Number(str));
}

// Example usage:
console.log(isValidNumber("123"));   // Output: true
console.log(isValidNumber("abc"));   // Output: false
console.log(isValidNumber("12.34")); // Output: true
console.log(isValidNumber(""));      // Output: false
Medullated answered 15/2 at 5:0 Comment(0)
L
2

This is a fairly old question, but the first that turns up Googling, and having read through the answers there is a lot of confusion, and Node is very confusing when it comes to handling numbers...

A lot of the answers are good, and probably good enough for most cases, but I tried to leverage all of the "pit falls" and come up with a "safe" solution that would cover all the pointed out areas, and the (not so simple) solution I came up with is:

const isNum = (num) => typeof num !== 'object' && (!Number.isNaN(+(String((String(num) || '').replace(/[^0-9\.\-e]/, '') !== String(num) || num === '' ? NaN : num))));

This will work with most cases I found in this thread:

isNum('n') // false
isNum('') // false
isNum('\t') // false
isNum('\r\n what?') // false
isNum(null) // false
isnum(undefined) // false
isnum(NaN) // false

isNum(0) // true
isNum('0') // true
isNum(-0) // true
isNum('1.23') // true
isNum(1.23) // true
isNum(4.917736942280289e-10) // true
isNum(BigInt("0b11111111111111111111111111111111111111111111111111111")) // true
isNum(0b11111111111111111111111111111111111111111111111111111) // true

EDIT: As we decided to start using this globally in our company, I published it as an npm package for anyone interested:

const { isNum } = require('@qvalia/isnum');

console.log(`isNum('abc')=${isNum('abc')}`);
Lagrange answered 8/3 at 7:42 Comment(0)
N
1

Here's an elegant one-liner to check if sNum is a valid numeric value. The code has been tested for a wide variety of inputs as well.

// returns True if sNum is a numeric value    
!!sNum && !isNaN(+sNum.replace(/\s|\$/g, ''));  

Hat tip to @gman for catching the error.

Nejd answered 27/11, 2017 at 16:25 Comment(0)
A
1

I often employ a method of iterating and checking each character of a string for my checks:

const isInt = aString => aString.length !== 0 && [...aString].every(char => ! Number.isNaN(char));

const isDecimal = aString =>
{
    if (aString.length === 0)
    {
        return false;
    }

    const chars = [...aString];

    return chars.filter(aChar => aChar === ".").length === 1 && chars.filter(aChar => aChar !== ".").every(char => ! Number.isNaN(char));
};

These methods could be further optimized as much as you like. For instance they both require creating a new string array and the decimal check function iterates through all the characters of the string being checked twice. But I find that these get the job done and haven't noticed any bottlenecks from them before.

Althing answered 21/3, 2023 at 3:8 Comment(0)
B
0

In my application we are only allowing a-z A-Z and 0-9 characters. I found the answer above using " string % 1 === 0" worked unless the string began with 0xnn (like 0x10) and then it would return it as numeric when we didn't want it to. The following simple trap in my numeric check seems to do the trick in our specific cases.

function isStringNumeric(str_input){   
    //concat a temporary 1 during the modulus to keep a beginning hex switch combination from messing us up   
    //very simple and as long as special characters (non a-z A-Z 0-9) are trapped it is fine   
    return '1'.concat(str_input) % 1 === 0;}

Warning : This might be exploiting a longstanding bug in Javascript and Actionscript [Number("1" + the_string) % 1 === 0)], I can't speak for that, but it is exactly what we needed.

Balloon answered 8/7, 2014 at 15:22 Comment(3)
Why would that be a bug in JavaScript?Cobra
I simply don't see the same behavior with a similar solution in perl or C, and since I'm not a programming language developer for javascript or actionscript I don't know whether the behavior I am experiencing is truly intentional or not.Balloon
Well, javascript is a bit sloppy about implicit type casting, but once you know that you can easily understand how it works. You're casting strings to numbers (by invocing the numerical % 1 operation on them), and that will interpret the string as a hex or float literal.Cobra
D
0

My solution:

// returns true for positive ints; 
// no scientific notation, hexadecimals or floating point dots

var isPositiveInt = function(str) { 
   var result = true, chr;
   for (var i = 0, n = str.length; i < n; i++) {
       chr = str.charAt(i);
       if ((chr < "0" || chr > "9") && chr != ",") { //not digit or thousands separator
         result = false;
         break;
       };
       if (i == 0 && (chr == "0" || chr == ",")) {  //should not start with 0 or ,
         result = false;
         break;
       };
   };
   return result;
 };

You can add additional conditions inside the loop, to fit you particular needs.

Deferred answered 7/8, 2014 at 22:42 Comment(0)
A
0

My attempt at a slightly confusing, Pherhaps not the best solution

function isInt(a){
    return a === ""+~~a
}


console.log(isInt('abcd'));         // false
console.log(isInt('123a'));         // false
console.log(isInt('1'));            // true
console.log(isInt('0'));            // true
console.log(isInt('-0'));           // false
console.log(isInt('01'));           // false
console.log(isInt('10'));           // true
console.log(isInt('-1234567890'));  // true
console.log(isInt(1234));           // false
console.log(isInt('123.4'));        // false
console.log(isInt(''));             // false

// other types then string returns false
console.log(isInt(5));              // false
console.log(isInt(undefined));      // false
console.log(isInt(null));           // false
console.log(isInt('0x1'));          // false
console.log(isInt(Infinity));       // false
Aged answered 12/9, 2015 at 14:3 Comment(2)
It's not too bad, two bad it does not work for any non-decimal notation, such as (1) scientific notation and (2) not-base-10 notation, such as octal (042) and hexadecimal (0x45f)Scarletscarlett
This does not answer the question of looking for a numeric value, it only looks for an int.Kevon
T
0

You could make use of types, like with the flow library, to get static, compile time checking. Of course not terribly useful for user input.

// @flow

function acceptsNumber(value: number) {
  // ...
}

acceptsNumber(42);       // Works!
acceptsNumber(3.14);     // Works!
acceptsNumber(NaN);      // Works!
acceptsNumber(Infinity); // Works!
acceptsNumber("foo");    // Error!
Tahmosh answered 16/11, 2017 at 15:13 Comment(0)
S
0

Here is a high-performance (2.5*10^7 iterations/s @3.8GHz Haswell) version of a isNumber implementation. It works for every testcase i could find (including Symbols):

var isNumber = (function () {
  var isIntegerTest = /^\d+$/;
  var isDigitArray = [!0, !0, !0, !0, !0, !0, !0, !0, !0, !0];
  function hasLeading0s (s) {
    return !(typeof s !== 'string' ||
    s.length < 2 ||
    s[0] !== '0' ||
    !isDigitArray[s[1]] ||
    isIntegerTest.test(s));
  }
  var isWhiteSpaceTest = /\s/;
  return function isNumber (s) {
    var t = typeof s;
    var n;
    if (t === 'number') {
      return (s <= 0) || (s > 0);
    } else if (t === 'string') {
      n = +s;
      return !((!(n <= 0) && !(n > 0)) || n === '0' || hasLeading0s(s) || !(n !== 0 || !(s === '' || isWhiteSpaceTest.test(s))));
    } else if (t === 'object') {
      return !(!(s instanceof Number) || ((n = +s), !(n <= 0) && !(n > 0)));
    }
    return false;
  };
})();
Sile answered 13/8, 2019 at 12:53 Comment(0)
T
0

Test if a string or number is a number

const isNumeric = stringOrNumber =>
  stringOrNumber == 0 || !!+stringOrNumber;

Or if you want to convert a string or number to a number

const toNumber = stringOrNumber =>
  stringOrNumber == 0 || +stringOrNumber ? +stringOrNumber : NaN;
Terpsichorean answered 17/7, 2021 at 4:39 Comment(0)
B
0

I used this function in Angular

 isNumeric(value: string): boolean {
             let valueToNumber = Number(value);
             var result = typeof valueToNumber == 'number' ;
             if(valueToNumber.toString() == 'NaN')
             {
                result = false;
             }
             return result;
          }
Bakki answered 7/1, 2022 at 23:22 Comment(1)
What's wrong with const isNumeric = (value: string) => !(Number(value).toString() == 'NaN'); ?Ulpian
G
0

If you only want to support positive integers and forbid any other characters, you can use this function:

const isNumeric = value =>
  value.length !== 0 && [...value].every(c => c >= '0' && c <= '9');
isNumeric('')          // false
isNumeric('1234')      // true
isNumeric('1234asdf')  // false

To include negative numbers, change the condition as follows:

const isNumeric = value =>
  value.length !== 0 &&
  [...(value[0] === '-' ? value.slice(1) : value)].every(c => c >= '0' && c <= '9');

isNumeric("1234")       // true
isNumeric("-1234")      // true
isNumeric("-1234asdf")  // false
Garfield answered 3/5, 2023 at 12:42 Comment(1)
what about negative?Pathogen
M
0

I didn't like the provided solutions because I only need numbers.

nums = new Set(['1','2','3','4','5','6','7','8','9','0']);
hasOnlyNumbers= str =>[...str].every( x=>nums.has(x) );

https://jsfiddle.net/gaby_de_wilde/05fb7k3g/

If you want to allow minus (ignore minus at start of string)

nums = new Set(['1','2','3','4','5','6','7','8','9','0']);
hasOnlyNumbers=str=>[...str[0]=='-'?str.substring(1):str].every(x=>nums.has(x));

https://jsfiddle.net/gaby_de_wilde/y4fdwvxk/

If you want it more readable:

nums = new Set(['1','2','3','4','5','6','7','8','9','0']);
hasOnlyNumbers = function(str){
  if(str[0]=='-'){ 
    str = str.substring(1) 
  }
  return [...str].every(x=>nums.has(x));
}

https://jsfiddle.net/gaby_de_wilde/6a5qwx2t/

allow a single dot (allow at most 1)

nums = new Set(['.','1','2','3','4','5','6','7','8','9','0']);
hasOnlyNumbers=str=>str.split('.').length<3&&[...str[0]=='-'?str.substring(1):str].every(x=>nums.has(x));

https://jsfiddle.net/gaby_de_wilde/hnx8d6so/

more readable:

nums = new Set(['.','1','2','3','4','5','6','7','8','9','0']);
hasOnlyNumbers = function(str){
  if(str.split('.').length > 2) { 
    return false 
  }
  if(str[0]=='-'){ 
    str = str.substring(1) 
  }
  return [...str].every(x=>nums.has(x));
}

https://jsfiddle.net/gaby_de_wilde/sz7e95mw/

Note: the Set now has a dot too.

Marigolda answered 4/5, 2023 at 0:48 Comment(0)
M
0
    function isValidNumber(str) {
        return !isNaN(parseFloat(str));
    }
    
    // Example usage:
    console.log(isValidNumber("123")); // true
    console.log(isValidNumber("abc")); // false

Using regular expression:

function isValidNumber(str) {
    return /^-?\d*\.?\d+$/.test(str);
}

    // Example usage:
    console.log(isValidNumber("123")); // true
    console.log(isValidNumber("123.45")); // true
    console.log(isValidNumber("abc")); // false
Medullated answered 29/2 at 14:24 Comment(0)
F
-1

Just use isNaN(), this will convert the string to a number and if get a valid number, will return false...

isNaN("Alireza"); //return true
isNaN("123"); //return false
Flagellate answered 31/1, 2019 at 11:52 Comment(0)
H
-1

I'm using the following:

const isNumber = s => !isNaN(+s)
Horripilate answered 5/3, 2019 at 7:54 Comment(1)
Works relatively well is many cases, but fails cases like 1..1, 1,1, -32.1.12, and more importantly fails undefined and NaN. If you passed undefined or a NaN that it would return you a false positive saying it was a number.Kevon
G
-1

If you are looking for a positive number (housenumber for example), just use:

if (mystring > 0) ...
Glauce answered 1/10, 2021 at 8:33 Comment(0)
M
-2

If you like a tricky way and you like getting your coworkers confused, you can use:

const isNumeric = str => parseFloat(str) === parseFloat(str)

Proof:

 const isNumeric = str => parseFloat(str) === parseFloat(str)
 
console.log(isNumeric('10'))
console.log(isNumeric('-10.2'))
console.log(isNumeric('15abc'))
console.log(isNumeric('0.0001'))
console.log(isNumeric('abc'))
console.log(isNumeric('abc123'))
Maomaoism answered 14/6, 2022 at 16:22 Comment(2)
This does not work in all cases and permits values that are not valid. In the example you gave, the third test case for '15abc' returns true, it should return false.Replenish
@Replenish this is an alternative format of an already accepted answer. 15abc returns true because it starts with a number, thus it's parsableMaomaoism
J
-2

How about the following?

const a = '1'

const isNumber = (a) => Number(a) === +a

Josphinejoss answered 22/6, 2022 at 16:33 Comment(0)
S
-5

I do it like this:

function isString(value)
{
    return value.length !== undefined;
}
function isNumber(value)
{
    return value.NaN !== undefined;
}

Of course isString() will be tripped up here if you pass some other object that has 'length' defined.

Scandinavian answered 13/10, 2014 at 15:1 Comment(2)
You mean like an Array? :-/Hatchel
I'm not sure what you're going for with your isNumber method. Strings and numbers never have a NaN property, that's only on the built-in Number constructor function.Nittygritty

© 2022 - 2024 — McMap. All rights reserved.