13

In PHP, it's pretty easy:

is_numeric(23);//true
is_numeric("23");//true
is_numeric(23.5);//true
is_numeric(true);//false

But how do I do this in Javascript? I could use a regular expression, but is there a function for this?

Vordreller
  • 2,524
  • 10
  • 34
  • 51
  • possible duplicate of [Validate numbers in JavaScript - IsNumeric()](http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric) – acdcjunior Feb 27 '14 at 16:24

9 Answers9

28

What about:

function isNumber(n){
    return typeof(n) != "boolean" && !isNaN(n);
}

The isNaN built-in function is used to check if a value is not a number.

Update: Christoph is right, in JavaScript Boolean types are convertible to Number, returning the 1 for true and 0 for false, so if you evaluate 1 + true the result will be 2.

Considering this behavior I've updated the function to prevent converting boolean values to its numeric representation.

Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • -1: doesn't work, eg `!isNaN(true)` is `true` because `isNaN(foo)` is equivalent to `isNaN(Number(foo))` – Christoph Mar 02 '09 at 10:42
  • 1
    -1: This does not work! Passing an empty string or null returns true in IE7! Should be: return n != null && n != "" && typeof(n) != "boolean" && !isNaN(n); – Josh Stodola Mar 11 '09 at 23:25
  • 1
    Even the space character returns true, so there's more work to be done! – Josh Stodola Mar 11 '09 at 23:26
  • @acdcjunior, right, check this answer for a better approach, backed with 30+ tests: http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric/1830844#1830844 – Christian C. Salvadó Feb 27 '14 at 07:15
16

I don't think any of the suggestions till now actually work. Eg

!isNaN(parseFloat(foo))

doesn't because parseFloat() ignores trailing non-numeric characters.

To work around this, you could compare the returned value to the one returned by a cast via Number() (or equivalently by using unary +, but I prefer explicit casting):

parseFloat(foo) === Number(foo)

This will still work if both functions return NaN because NaN !== NaN is true.

Another possibility would be to first cast to string, then to number and then check for NaN, ie

!isNaN(Number(String(foo)))

or equivalently, but less readable (but most likely faster)

!isNaN(+('' + foo))

If you want to exclude infinity values, use isFinite() instead of !isNaN(), ie

isFinite(Number(String(foo)))

The explicit cast via Number() is actually unnecessary, because isNan() and isFinite() cast to number implicitly - that's the reason why !isNaN() doesn't work!

In my opinion, the most appropriate solution therefore would be

isFinite(String(foo))

As Matthew pointed out, the second approach does not handle strings that only contain whitespace correctly.

It's not hard to fix - use the code from Matthew's comment or

isFinite(String(foo).trim() || NaN)

You'll have to decide if that's still nicer than comparing the results of parseFloat() and Number().

Christoph
  • 164,997
  • 36
  • 182
  • 240
  • 1
    This gives false positives for `isFinite(String(""))` and `isFinite(String(" "))`. Perhaps use `String(foo).trim() !== "" && isFinite(String(foo))`? – Matthew Strawbridge Jun 27 '13 at 16:21
  • @MatthewStrawbridge: note that `parseFloat(...) === Number(...)` correctly handles this case; I'll see if I can save the 2nd approach – Christoph Jun 27 '13 at 16:31
6

To check types in javascript you can use the typeof operator:

js> var x = 1;
js> typeof(x);
number

So:

if (typeof(x) === 'number') {
   // Do something
}

If you want to coerce the value of a variable to an integer, you can use parseInt(x, 10) which will parse the value as an integer in base 10. Similarly, you can use parseFloat if you want a floating point value. However, these will always coerce regardless of type so passing null, true, etc will always return a number. However, you can check whether its a valid number by calling isNaN.

So, putting it all together:

!isNaN(parseFloat(23)) // true
!isNaN(parseFloat('23')) // true
!isNaN(parseFloat(23.5)) // true
!isNaN(parseFloat(true)) // false

or

function isNumber(x) {
    return !isNaN(parseFloat(x));
}
Bryan Kyle
  • 13,361
  • 4
  • 40
  • 45
4

This checks for numerical values, including negative and floating point numbers.

function is_numeric(val){
    return val && /^-?\d+(\.\d+)?$/.test(val + '');
}

@Vordreller: I corrected the Regex. It should work properly now.

Manu
  • 28,753
  • 28
  • 75
  • 83
2
function is_numeric(val) {
  return ((+val) == val);
}

That should do the trick.

Aistina
  • 12,435
  • 13
  • 69
  • 89
  • Oops, forgot about false. As for infinity, I do think that would be considered a number... +"==" returns 0, so that works as expected. I guess only true and false are special cases, depending on if you count Infinity or not. – Aistina Mar 02 '09 at 00:20
0

Here's what I came up with:

value = "2.34";
if (parseFloat(value).toString() === value) {
    alert("number");
}

This should work with floats and ints, positive and negative. I don't know about infinity, as some of the answers above have discussed.

If your value might actually be a number and not always a string, you can change the === to a == and it will handle both.

arlomedia
  • 8,534
  • 5
  • 60
  • 108
0

Here's some benchmarks for isNaN vs. isFinite and typeof === "number"

http://jsperf.com/isnan-vs-isfinite-vs/3

Apparently typeof === "number" is roughly 5 times faster

TheJKFever
  • 685
  • 7
  • 25
0

Run the code snippet to see comparisons of top answers on this topic.

Some test cases are not highlighted (and don't contribute to the summary). These cases are flagged as ambiguous because it is not clear whether a given value should or should not be considered a number.

// Each of these functions should output a truthy/falsy value if the input is
// a number
const solutionsToTest = [
  v => parseFloat(v),
  v => Number(v),
  v => !isNaN(v),
  v => typeof v != "boolean" && !isNaN(v),
  v => isFinite(String(v)),
  v => !isNaN(parseFloat(v)) && isFinite(v)
];

const testCases = [
  //[ Test Name, Test Value, Expected Output, Is Ambiguous ]

  // Whitespace
  ['""', "", false, false],
  ['"\\t"', "\t", false, false],
  ['" "', " ", false, false],

  // Infinity
  ['"Infinity"', "Infinity", false, true],
  ['"+Infinity"', "Infinity", false, true],
  ["-Infinity", -Infinity, false, true],
  ["Infinity", Infinity, false, true],

  // Numbers mixed with symbols
  ['"123abc"', "123abc", false, true],
  ['"abc123"', "abc123", false, false],
  ['".0."', ".0.", false, false],
  ['"1."', "1.", true, true],
  ['"."', ".", false, true],
  ['"01"', "01", true, true],
  ['"-0"', "-0", true, true],
  ["+1", +1, true, true],
  ["-1", -1, true, true],

  // Other js types
  ["'null'", "null", false, false],
  ["'true'", "true", false, false],
  ["'false'", "false", false, false],
  ["null", null, false, false],
  ["true", true, false, false],
  ["false", false, false, false],
  ["NaN", NaN, false, false],
  ["[]", [], false, false],
  ["{}", {}, false, false],
  ["/./", /./, false, false],
  ["() => {}", () => {}, false, false]
];

const styles = {
  code: {
    fontFamily: "monospace",
    fontSize: 16
  },
  success: {
    backgroundColor: "#00ff5478"
  },
  failure: {
    backgroundColor: "#ff00008c"
  }
};

class TestCaseTable extends React.Component {
  static renderTableHeader(solutionsToTest) {
    return (
      <tr>
        <th>
          <p>Test Case</p>
        </th>
        {solutionsToTest.map(f => (
          <th key={f.toString()}>
            <p style={styles.code}>{f.toString()}</p>
          </th>
        ))}
      </tr>
    );
  }
  static renderTableRow(testCase, solutionsToTest) {
    const [testName, input, expectedOutput, isAmbiguous] = testCase;
    return (
      <tr key={testName}>
        <td style={styles.code}>{testName}</td>
        {solutionsToTest.map(f => {
          const output = Boolean(f(input));
          const style = isAmbiguous
            ? {}
            : output == expectedOutput ? styles.success : styles.failure;
          return (
            <td style={style} key={f.toString()}>
              <p>{output + ""}</p>
            </td>
          );
        })}
      </tr>
    );
  }
  render() {
    // Sort test cases, put the ambiguous ones after (but maintain stable sort
    // order)
    let sortedCases = [
      ...testCases.filter(([a, b, c, ambiguous]) => !ambiguous),
      ...testCases.filter(([a, b, c, ambiguous]) => ambiguous)
    ];
    return (
      <table>
        <thead>{TestCaseTable.renderTableHeader(solutionsToTest)}</thead>
        <tbody>
          {sortedCases.map(tc =>
            TestCaseTable.renderTableRow(tc, solutionsToTest)
          )}
        </tbody>
      </table>
    );
  }
}
class TestCaseSummaryTable extends React.Component {
  renderTableHeader(solutionsToTest) {
    return (
      <tr>
        <th>Summary</th>
        {solutionsToTest.map(f => (
          <th key={f.toString()}>
            <p style={styles.code}>{f.toString()}</p>
          </th>
        ))}
      </tr>
    );
  }
  renderSuccessRateRow(solutionsToTest, testCases) {
    // Ignore potentially ambiguous test cases
    testCases = testCases.filter(
      ([name, input, expected, ambiguous]) => !ambiguous
    );

    const numSuccess = testSolution =>
      testCases.reduce((succeeded, [name, input, expected]) => {
        return succeeded + (Boolean(testSolution(input)) == expected ? 1 : 0);
      }, 0);

    return (
      <tr>
        <td>
          <p>Test Success</p>
        </td>
        {solutionsToTest.map(f => (
          <td>
            <p>
              {numSuccess(f)} / {testCases.length}
            </p>
          </td>
        ))}
      </tr>
    );
  }
  render() {
    return (
      <table>
        <thead>{this.renderTableHeader(solutionsToTest)}</thead>
        <tbody>{this.renderSuccessRateRow(solutionsToTest, testCases)}</tbody>
      </table>
    );
  }
}

const root = () => {
  return (
    <div>
      <TestCaseSummaryTable />
      <TestCaseTable />
    </div>
  );
};

ReactDOM.render(root(), document.querySelector("#application"));
td {
  text-align: center;
  vertical-align: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="application"></div>
cdosborn
  • 3,111
  • 29
  • 30
0

Here is my Solution : ES6/2015

Disclaimer: This solution works only if user send a Number Type as an input. For Example: 23 is a number type but '23' is not a number type it is a String Type.

function isValidNumber(value) {
  return typeof value === 'number' && Number.isNaN(value) === false;
}

Test Cases

isValidNumber(10) // true
isValidNumber(10.34) // true
isValidNumber('geo10') // false
isValidNumber('10geo') // false
isValidNumber('') // false
isValidNumber(NaN) // false
isValidNumber(true) // false
isValidNumber(false) // false
  • Your function didn't pass OP's case, `isValidNumber('23') //fasle` – foxiris Mar 17 '20 at 10:59
  • @foxiris: I have now added a disclaimer to my solution. My solution basically works only when the input is exactly a Number data type like 23 and not a 'String Type' like '23'. Also, a perfect solution to this problem is a bit tricky as Javascript behaves differently than other traditional languages. For a near perfect solution we can go for 3rd party JS libraries like lodash _.isNumber(). – rajeshchauhan23102008 Mar 28 '20 at 16:04