23

Defaulting the radix to 8 (if the string starts with a 0) in JavaScript's parseInt function annoys me, only because I continue to forgot to pass the optional second argument as 10. I'm looking for an answer telling me why it makes sense to have it default to 8.

Kirk Ouimet
  • 27,280
  • 43
  • 127
  • 177

3 Answers3

34

It only "defaults" to 8 if the input string starts with 0. This is an unfortunate carryover from C and C++.

You can use Number('0123') instead, or, as you said in the question, parseInt('0123', 10).

How do I work around JavaScript's parseInt octal behavior?


Can you tell me more about this carryover?


Note: ECMAScript strict mode removes octal syntax.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • Can you tell me more about this carryover? – Kirk Ouimet Apr 08 '11 at 20:23
  • 2
    Yes. It is stupid, evil, bad, and obnoxious - a poorly designed "feature" implemented solely because previous languages did it. – Matt Ball Apr 08 '11 at 20:26
  • 2
    A unary `+` is a better choice than using `Number`. Unary `+` ignores octal formats (but still honors hexadecimal formats) and is faster than a function call. – Reid Apr 08 '11 at 20:55
  • 2
    @Reid: the better choice depends on your usage. As for performance, I'm not 100% sure that `+` is faster (and it almost certainly isn't the same for all browsers). Let's see: http://jsperf.com/string-to-int-2 – Matt Ball Apr 08 '11 at 21:11
  • Since when has C(++) had parseInt? Surely only this aspect of integer literals is (or was, before it was removed in ECMAScript 5) a carryover, and how parseInt behaves is another matter altogether. – Stewart Feb 09 '21 at 13:39
  • @Stewart _"unfortunate carryover from C and C++"_ was a reference to how int literals are interpreted in those languages, not a specific `parseInt` routine. – Matt Ball Feb 09 '21 at 20:11
  • @MattBall Your answer makes no mention of how integer literals are interpreted, therefore your "This" is a dangling reference. – Stewart Mar 02 '21 at 14:51
9

If a number starts with 0 and contains digits between (and inclusive) 0 to 7, it is interpreted as an octal number (with base 8 instead of 10).

In parseInt however, if a string starts with a 0 it's always interpeted as an octal, and stops searching when it encounters an invalid character (e.g. the digits 8 or 9 or a character like z).

parseInt("070");     //56
parseInt("70");      //70
parseInt("070", 10); //70
parseInt("78");      //78
parseInt("078");     //7, because it stops before 8

If you need to convert a string into a number, and you're sure that it contains no invalid characters or fractional parts, you can multiply it with 1 to make a number of it:

1 * "070";           //70

I personally prefer this approach, and believe it's faster than calling functions.

Lekensteyn
  • 64,486
  • 22
  • 159
  • 192
  • 2
    For those who do not understand what Matt Ball is talking about, the first answer submitted contained the first paragraph only. – Lekensteyn Apr 08 '11 at 20:28
  • 1
    All this is out of date now. Previously, an integer literal beginning with 0 was notated as octal, but it is now illegal (see also my comment on Matt's answer). But I'm informed that this behaviour of parseInt was never part of the standard, and nowadays the standard dictates that parseInt with one argument always uses decimal. – Stewart Feb 09 '21 at 13:45
5

Now, a couple of years later, parseInt() seems to work fine with numbers starting with 0. Current browsers:

parseInt("019"); // 19 on Firefox 67
parseInt("019"); // 19 on Chrome 75
parseInt("019"); // 19 on Safari 12
parseInt("019"); // 19 on IE 11
parseInt("019"); // 19 on Edge 42

But still, this "fix" must break older scripts that rely on parseInt("019") returning 1 or 0 instead of 19...

kraftwer1
  • 5,253
  • 10
  • 36
  • 54
  • Does that hold for `Number.parseInt` too? – sandstrom May 18 '20 at 08:46
  • 1
    Does it make any difference that `019` wouldn't be a valid octal number anyway, as it contains the digit 9? [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#using_parseint) uses the example of `015`, but I don't know whether or not it's significant that all the digits are below 8. – Tim Jan 07 '21 at 09:52
  • 1
    @Tim Even `015` seems to be working as base 10 now on both Firefox and Chrome. And I believe it's a relatively recent change, I was still bitten by it one or two years ago (or maybe it's node.js? It works fine now too on v12.20+). – fireattack May 01 '21 at 23:18