Newsletter

JavaScript string to number: parseInt, parseFloat, Number() and +

Four ways to convert a string to a number in JavaScript, how they differ on “42px”, “3,99” or an empty string, how to handle NaN, and which method to pick for each case.

JavaScript string to number: parseInt, Number and the + operator
Quick answer

Use Number(chaine) to convert a string that must be entirely numeric (“42”, “3.99”): it returns NaN at the first stray character. Use parseInt(chaine, 10) or parseFloat(chaine) to extract the number at the start of a string such as “42px”. Always check the result with Number.isNaN() before doing any arithmetic.

A value read from a form field, an HTML attribute, a URL or a badly typed JSON file always arrives as a string. Before you can calculate with it, you have to convert it to a number. JavaScript offers four ways to do that, and they do not react the same way to “42px”, “3,99” or an empty string. Here is what each one really returns, checked under Node.js 22.

The four methods in one table

String parseInt(s, 10) parseFloat(s) Number(s) +s
"42" 42 42 42 42
"3.99" 3 3.99 3.99 3.99
"42px" 42 42 NaN NaN
" 42 " 42 42 42 42
"" (empty) NaN NaN 0 0
"12,5" 12 12 NaN NaN
"1e3" 1 1000 1000 1000
"0x1f" 0 (radix 10 forced) 0 31 31
"abc" NaN NaN NaN NaN
"Infinity" NaN Infinity Infinity Infinity
null NaN NaN 0 0
undefined NaN NaN NaN NaN

Two families emerge. parseInt and parseFloat extract: they read the string from the start, stop at the first character that is not a digit and return what they have read so far. Number() and the + operator convert all or nothing: the whole string must represent a number, otherwise the result is NaN. One exception that stings: for them, the empty string is 0.

parseInt(): the integer at the start of the string

javascript
parseInt('42', 10);      // 42
parseInt('42px', 10);    // 42  : stops at the “p”
parseInt('3.99', 10);    // 3   : the decimal part is dropped, not rounded
parseInt('  42  ', 10);  // 42  : surrounding spaces are tolerated
parseInt('abc', 10);     // NaN : no digit at the start
parseInt('', 10);        // NaN

The second argument is the radix (or base). It is 10 for a decimal number, 16 for hexadecimal, 2 for binary:

javascript
parseInt('ff', 16);   // 255
parseInt('101', 2);   // 5
parseInt('0x1f');     // 31 : without a radix, the 0x prefix switches to hexadecimal
parseInt('08');       // 8  : modern engines no longer read “08” as octal

Writing the radix explicitly, parseInt(s, 10), has not been essential for leading zeros since ES5, but it is still the right habit: it makes the intention readable and neutralises the 0x case.

parseFloat(): the decimal number at the start of the string

javascript
parseFloat('3.99');     // 3.99
parseFloat('12.5px');   // 12.5
parseFloat('.5');       // 0.5
parseFloat('1e3');      // 1000 : scientific notation is understood
parseFloat('3,99');     // 3    : the comma stops the parsing
parseFloat('abc');      // NaN

parseFloat has no radix argument: it always reads in decimal. It is the function to pick for extracting a measurement from a CSS string (“12.5px”, “1.5rem”) or from free text.

Number(): strict conversion

javascript
Number('42');       // 42
Number('3.99');     // 3.99
Number('  42  ');   // 42  : surrounding spaces and line breaks are ignored
Number('42px');     // NaN : one extra character and the whole thing fails
Number('');         // 0   : watch out
Number(' ');        // 0   : same again
Number(null);       // 0
Number(undefined);  // NaN
Number(true);       // 1
Number('0x1f');     // 31  : prefixed hexadecimal, binary (0b) and octal (0o) are accepted

Number() is the conversion you want for a value that must be a number and nothing else: a price, a quantity, an identifier. If the user typed “12 euros”, you get NaN and you can tell them so, instead of unknowingly calculating with 12.

The unary + operator: Number() in a single character

javascript
+'42';     // 42
+'';       // 0
+'abc';    // NaN
'42' * 1;  // 42  : multiplication also forces the conversion
'42' - 0;  // 42
'3' + '4'; // '34' : addition, on the other hand, concatenates!

A + placed in front of a value applies exactly Number(). It is short, very common in existing code, and easy to miss in a code review: +valeur looks like a typo. In shared code, Number(valeur) says the same thing more clearly. And never use binary addition to convert: '3' + '4' gives the string '34'.

Handling NaN properly

NaN (Not a Number) is the result of any failed conversion. It has a treacherous property: it is equal to nothing, not even itself.

javascript
const n = Number('abc');

n === NaN;          // false, always
Number.isNaN(n);    // true  : the right way to test
isNaN('abc');       // true  : but isNaN converts its argument first...
Number.isNaN('abc');// false : ... whereas Number.isNaN only tests for genuine NaN

The usual pattern: convert, test, then apply a default value or report the error.

toNumber.js
function toNumber(valeur, defaut = 0) {
  const n = Number(String(valeur).trim());
  return Number.isNaN(n) ? defaut : n;
}

toNumber('42');    // 42
toNumber('42px');  // 0  (default value)
toNumber('', 10);  // 0  : the empty string is 0, not the default value

The last line is a reminder of the empty-string trap: if an empty field must be treated as “not provided”, test for it before converting.

javascript
function toNumberStrict(valeur) {
  const s = String(valeur).trim();
  if (s === '') return NaN;
  return Number(s);
}

The French case: the decimal comma

None of the four methods understands “12,5”. Number returns NaN, and parseFloat stops at the comma and returns 12, which is worse: the program carries on with a wrong value. Normalise the input before converting.

parseFr.js
function parseFr(chaine) {
  const normalisee = String(chaine)
    .replace(/\s/g, '')   // removes the thousands spaces: “1 234,56”
    .replace(',', '.');   // decimal comma -> point
  return Number(normalisee);
}

parseFr('12,5');       // 12.5
parseFr('1 234,56');   // 1234.56
parseFr('12.5');       // 12.5 : the point is still accepted

In a form, <input type="number"> avoids the problem: the browser shows the comma to a French user but always passes a point in value.

Checking that a string really is a number

To find out whether a string represents a number before using it, combine a strict conversion with Number.isFinite, which rejects both NaN and Infinity.

javascript
function estNumerique(chaine) {
  const s = String(chaine).trim();
  return s !== '' && Number.isFinite(Number(s));
}

estNumerique('42');       // true
estNumerique('3.99');     // true
estNumerique('42px');     // false
estNumerique('');         // false
estNumerique('Infinity'); // false

And to tell an integer from a decimal once converted: Number.isInteger(42) is true, Number.isInteger(3.99) is false.

Large integers: when Number is no longer enough

Number represents integers exactly up to 253 − 1 (9,007,199,254,740,991). Beyond that, precision is lost without warning: a 64-bit database identifier or a very large amount expressed in cents can come out wrong.

javascript
Number('9007199254740993');   // 9007199254740992 : the last digit has changed
BigInt('9007199254740993');   // 9007199254740993n : exact
Number.MAX_SAFE_INTEGER;      // 9007199254740991

BigInt cannot be mixed with Number in a calculation and does not accept decimals; keep it for identifiers and genuinely large integers.

Which method to choose?

  • The value must be a number and nothing else (price, quantity, identifier): Number(), after ruling out the empty string.
  • You need to extract a number from text (“12.5px”, “3 items”): parseFloat() for a decimal, parseInt(s, 10) for an integer.
  • The input comes from a French user: normalise the comma and the spaces, then Number().
  • You are reading code that uses +valeur: it is Number(valeur). Keep it if the team is used to it, but never convert with the addition '3' + '4'.
  • In every case: test with Number.isNaN() or Number.isFinite() before calculating.

The reverse operation, turning a number into a readable string with two decimal places or a thousands separator, is covered in Formatting a number in JavaScript. For the basics of the language, the Variables and data types chapter of the tutorial explains why a string and a number are two distinct types.

Common errors

Forgetting the parseInt radix parseInt("08") is 8 in every modern engine, but parseInt("0x1f") is 31: the string is read as hexadecimal. Always pass the radix: parseInt(chaine, 10).
Relying on the French decimal comma Number("12,5") returns NaN and parseFloat("12,5") returns 12. Replace the comma with a point before converting.
Testing NaN with === NaN === NaN is false. Use Number.isNaN(valeur), never a direct comparison.
Confusing the empty string with zero Number("") and +"" are 0, not NaN. A form field left empty therefore becomes a silent zero: test chaine.trim() === "" before converting.

JavaScript

Damien Flandrin Web developer since 2010, creator of Gekkode and Email Impact. Every article is tested on a real project before publication. Contact
Newsletter

New tests, tutorials and projects, by e-mail.

Reproducible tests, versioned code, dated results. Never any spam.