Tuesday, February 12th, 2008

The parseInt gotcha

Category: JavaScript, Tip

Guyon Morée has posted the old chesnut parseInt gotcha, so I thought I should put it up here as a quick tip:

I was working on some stuff in javascript which involved some date/string parsing when one morning it failed. “That’s weird, yesterday it worked fine!”
After some debugging with FireBug I found parseInt() was failing on me.

It was the 8th of February and it was failing on “08” as an input string. I opened the FireBug console and entered parseInt(“08”), just to be sure I wasn’t’ getting mad and sure enough, the output was 0. Just as a way of rechecking my sanity I entered parseInt(’07’) and this did return the correct answer, 7.

So I googled the parseInt function and discovered some funky default behavior, which was flagged as deprecated.
The parseInt takes a second radix parameter. With this you can tell parseInt the base your input is in.

All fine, but there are also some prefixes defined, so you can input ‘0xff’ for hexadecimal values. Unfortunately they also thought it would be smart to assign 0 to octal values. So 08 is being intepreted as an octal value.

Even though I think the behavior is error prone, it’s even weirder that it returns 0. I believe it should return something like NaN as it is isn’t a valid number in the assumed base.

Mike Owens posted the Prototype based ‘+’ mapping to do the work for you:

javascript

  1. ['2008', '02', '11', '06', '21', '03'].map(function(v) { return + v });
  2. # [2008, 2, 11, 6, 21, 3]

Posted by Dion Almaer at 5:11 am
25 Comments

++---
2.6 rating from 41 votes

25 Comments »

Comments feed TrackBack URI

“All fine, but there are also some prefixes defined, so you can input ‘0xff’ for hexadecimal values. Unfortunately they also thought it would be smart to assign 0 to octal values. So 08 is being intepreted as an octal value.”

So, who will tell this guy that 0# is considered an octal number in almost every modern language?

Comment by urandom — February 12, 2008

Seriously ?!
Don’t people know their basic basis and how to read a spec these days ?

And suggesting that parseInt( ’08’ ); should return NaN is ludicrous.

Comment by Mathieu \'p01\' Henri — February 12, 2008

That is just one of the traps you can avoid using jslint. I listed some more hints on how to understand jslint here: http://wolfram.kriesing.de/blog/index.php/2007/understanding-jslint-output

Comment by Wolfram Kriesing — February 12, 2008

I don’t see why in the whole article there is not a single code example of how to do it properly (also jslint complains about leaving out the second param btw):
parseInt(myStringThatMightStartWithZeroButStillIsDecimal, 10)
Just always use it like that and be happy.

Comment by Alexander Kirk — February 12, 2008

parseDec(i) { return parseInt(i,10) } and you are all happy

Comment by Gordon — February 12, 2008

Thank you. The simplest things are sometimes the most difficult ones to remember.

Comment by ingdir — February 12, 2008

I know, cross-browser testing is out … I checked it on Firefox 2, IE7, Safari 3 Beta and Opera 9, all on Windows. They all returned 0, except Opera. Adding 10 as 2nd parameter to parseInt() returned the correct result in all 4 browsers.

Comment by wortwart — February 12, 2008

Mathieu: I don’t see how NaN would be more ludicrous than 0 or 10. Other than that, yes, passing the radix argument is _the_ solution.

Comment by Tim Cooijmans — February 12, 2008

NaN is a well-defined concept from floating point arithmetic. Since parseInt is supposed to return an integer, it therefore shouldn’t return NaN.

Comment by Joeri — February 12, 2008

The reason it COULD return NAN is because 08 is the prefix indicating that the number *following* it is in octal. Since there is *nothing* following it NAN would make sense.

Comment by Diodeus — February 12, 2008

His work around is pretty nice to, I have always used parseInt(foo, 10);

Comment by jdalton — February 12, 2008

Dion:

You should probably run your code through JSLint (http://jslint.com/). It would have thrown an error about the radix missing.

Comment by jaredmellentine — February 12, 2008

Considering javascript should be always as natural as possible to use why are we bother with plain old rules like “octal are starting with 0” ? (which may be an old International Business Machine hack)
Should not be a real ohhh ?
like o12 or 12o

Everyone can live better with the ohhh !

Comment by sebcreme — February 12, 2008

umm… Javascript is perfectly natural here, to the point where you typically shouldn’t resort to using parseInt! String->number coercion was the right solution all along, as the author discovered, and has exactly the behavior he was looking for — whether he used the plus trick or the explicit Number constructor or whatever. No need for fancy toolkits here until you need to iterate. He just shouldn’t have been using parseInt in the first place, which does very specific things which are also in line with the language, but obviously a bit more technical in nature (you might notice that number literals also respect the ohhh prefix!)

Comment by peller — February 12, 2008

But it worked yesterday? unfortunately the only thing that didn’t work was your ability to read the specs.

Comment by j4606 — February 12, 2008

Just a FYI, the snippet I posted to the gumuz’s blog using Prototype was just an example to show how the + operator responded to a list of date-like base-10 decimal strings. Obviously, there’s nothing Prototype-specific about the + operator.

You can read about it here: Javascript Type-Conversion.

– Mike Owens

Comment by sphivo — February 12, 2008

Sorry Tim, I lost touch with reality when I saw someone actually blogging his revelation about parseInt(). Indeed parseInt( ’08’ ); should return NaN since 08 is not a valid octal number. :p

Comment by p01 — February 12, 2008

aww, if i had known ajaxian would accept any submission I would have submitted my discovery of mozilla’s setTimeout’s extra parameter (the lateness) long ago.

Comment by cdude — February 12, 2008

I prefer this “String.prototype.parseInt=function(){return parseInt(this,10)}”

Comment by kcisoul — February 12, 2008

Wow…give the guy a break! He didn’t ask Ajaxian to make out this was some kind of major story. (Ajaxian has a habit of taking the most mundane stuff and giving it a high profile.)

And also, some respondents might do well to follow their own advice and read the spec; on the one hand we’re saying Guyon should read the spec, and in the same breath some people question why parseInt("08") returns 0 instead of NaN, proving that we can all overlook things, not just Guyon.

The answer, for those who understandably don’t want to wade through the specs (what are blogs for, after all), is that parseInt and related functions parse as much as they can from a string and then stop. So to illustrate, parseInt("23 days", 10) will return 23, and not Nan, because it will find as many base 10 numbers as it can before stopping.

This means that the example of parseInt("08") might as well be parseInt("0banana") for all that it means in octal–the answer is correctly zero.

Mark

Comment by MarkBirbeck — February 13, 2008

I agree with MarkBirbeck on this one… Why the harshness? Since when are we all above “learning”?! This post may in fact help quite a few people who may be scratching their heads as to why parseInt doesn’t behave as expected.

Give the hating a break already!

Comment by FrankManno — February 13, 2008

MarkBirbeck: Fair enough. If only the difference of time spent commenting on and stumbling on that parseInt() behavior and writting a blog post about it wasn’t so big.

FrankManno: I don’t see hatred in the comments. Harshness yes but no hatred.

Beside there are thousands of results when searching for parseInt 08 on the net.

Comment by p01 — February 13, 2008

To ease the mood, here is another potential gotcha: per ECMAscript 262-3 specification, Array.prototype.sort( [compareFunction] ) is not necessary stable, and therefore should not be assumed to be stable.

Comment by p01 — February 13, 2008

@MarkBirbeck: certainly no hatred intended on my part. I hope my comment wasn’t read as anything but constructive criticism. And yes, you give another very good reason why parseInt() is usually overkill and better replaced by coercion, IMO, unless you are doing it specifically because you want the behavior of parsing only the number portion.

Comment by peller — February 15, 2008

@sphivo: wow, that article is a gem. How interesting that coercion takes hex strings but not octal. Plenty of gotchas with either method, I guess.

Comment by peller — February 15, 2008

Leave a comment

You must be logged in to post a comment.