Portman
Portman

Reputation: 31975

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

Try executing the following in JavaScript:

parseInt('01'); //equals 1
parseInt('02'); //equals 2
parseInt('03'); //equals 3
parseInt('04'); //equals 4
parseInt('05'); //equals 5
parseInt('06'); //equals 6
parseInt('07'); //equals 7
parseInt('08'); //equals 0 !!
parseInt('09'); //equals 0 !!

I just learned the hard way that JavaScript thinks the leading zero indicates an octal integer, and since there is no "8" or "9" in base-8, the function returns zero. Like it or not, this is by design.

What are the workarounds?

Note: For sake of completeness, I'm about to post a solution, but it's a solution that I hate, so please post other/better answers.


Update:

The 5th Edition of the JavaScript standard (ECMA-262) introduces a breaking change that eliminates this behavior. Mozilla has a good write-up.

Upvotes: 286

Views: 65916

Answers (10)

Andrija
Andrija

Reputation: 14473

This issue cannot be replicated in latest* Chrome or Firefox (2019).

Test:

console.log(parseInt('08'));

*"Since (ECMAScript 5) JavaScript has abandoned this behaviour, but you should still specify the radix to satisfy older browsers." Source

Upvotes: 5

SoEzPz
SoEzPz

Reputation: 15912

You may also, instead of using parseFloat or parseInt, use the unary operator (+).

+"01"
// => 1

+"02"
// => 2

+"03"
// => 3

+"04"
// => 4

+"05"
// => 5

+"06"
// => 6

+"07"
// => 7

+"08"
// => 8

+"09"
// => 9

and for good measure

+"09.09"
// => 9.09

MDN Link

The unary plus operator precedes its operand and evaluates to its operand but attempts to convert it into a number, if it isn't already. Although unary negation (-) also can convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number.

Upvotes: 7

Paolo Bergantino
Paolo Bergantino

Reputation: 488344

This is a common Javascript gotcha with a simple solution:

Just specify the base, or 'radix', like so:

parseInt('08',10); // 8

You could also use Number:

Number('08'); // 8

Upvotes: 332

Gordon K
Gordon K

Reputation: 51

How about this for decimal:

('09'-0) === 9  // true

('009'-0) === 9 // true

Upvotes: 5

ingredient_15939
ingredient_15939

Reputation: 3124

If you've done a bunch of coding already with parseInt and don't want to add ",10" to everything, you can just override the function to make base 10 the default:

window._oldParseInt = window.parseInt;
window.parseInt = function(str, rad) {
    if (! rad) {
        return _oldParseInt(str, 10);
    }
    return _oldParseInt(str, rad);
};

That may confuse a later reader, so making a parseInt10() function might be more self-explanatory. Personally I prefer using a simple function than having to add ",10" all the time - just creates more opportunity for mistakes.

Upvotes: 4

Karl Guertin
Karl Guertin

Reputation: 4456

If you know your value will be in the signed 32 bit integer range, then ~~x will do the correct thing in all scenarios.

~~"08" === 8
~~"foobar" === 0
~~(1.99) === 1
~~(-1.99)  === -1

If you look up binary not (~), the spec requires a "ToInt32" conversion for the argument which does the obvious conversion to an Int32 and is specified to coerce NaN values to zero.

Yes, this is incredibly hackish but is so convenient...

Upvotes: 45

Andrew Duffy
Andrew Duffy

Reputation: 6928

Would it be very naughty to replace parseInt with a version that assumes decimal if it has no second parameter? (note - not tested)

parseIntImpl = parseInt
parseInt = function(str, base){return parseIntImpl(str, base ? base : 10)}

Upvotes: 7

Jason S
Jason S

Reputation: 189626

function parseDecimal(s) { return parseInt(s, 10); }

edit: making your own function, to do what you really want, is just an option if you don't like adding the ",10" all the time to the parseInt() call. It has the disadvantage of being a nonstandard function: more convenient for you if you use it a lot, but perhaps more confusing for others.

Upvotes: 12

RichieHindle
RichieHindle

Reputation: 281355

Specify the base:

var number = parseInt(s, 10);

Upvotes: 10

Portman
Portman

Reputation: 31975

From the parseInt documentation, use the optional radix argument to specify base-10:

parseInt('08', 10); //equals 8
parseInt('09', 10); //equals 9

This strikes me as pedantic, confusing, and verbose (really, an extra argument in every single parseInt?) so I'm hoping there is a Better Way.

Upvotes: 24

Related Questions