parseInt bug

733 views
Skip to first unread message

danp

unread,
Feb 21, 2012, 4:34:53 PM2/21/12
to nodejs
This is a V8 bug, but it's better to know it.

Parsing "08" or "09" with parseInt returns 0, not 8 or 9.

I've got out of mind to debug a peace of code that uses minutes from
the current time string, and goes wrong only at minute 8 and 9 of
every hour.
That's true since version 0.6.8 for sure.

Dan

Tim Caswell

unread,
Feb 21, 2012, 4:46:14 PM2/21/12
to nod...@googlegroups.com
It's not so much a V8 bug, but an unfortunate feature of JavaScript itself.  Crockford would call this one of the "bad parts".  parseInt() tries to be clever and guess the radix if you don't give it one.  Numbers starting with "0" are assumed to be octal (unless it starts with "0x" of course).

While it's annoying, it's a good idea to always specify the radix (the second argument to parseInt) when parsing numbers and you know the radix. This is why jslint yells at you if you leave this "optional" argument off.


--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

Tim Caswell

unread,
Feb 21, 2012, 4:50:06 PM2/21/12
to nod...@googlegroups.com
Actually, according to that mdn page I just linked, ES5 (which V8 implements) should not try to parse octal mode and in a way it's a bug.  But changing the behavior will "break the web" for sites that expect the ES3 behavior.  Isn't JavaScript versioning fun?

Andrew Chilton

unread,
Feb 21, 2012, 5:16:00 PM2/21/12
to nod...@googlegroups.com
On 22 February 2012 10:46, Tim Caswell <t...@creationix.com> wrote:
> While it's annoying, it's a good idea to always specify the radix (the
> second argument to parseInt) when parsing numbers and you know the
> radix. This is why jslint yells at you if you leave this "optional" argument
> off.

On a slightly different note, another good way (which Crockford also
suggests) is instead of using parseInt(), coerce the string into
number by using +'08'. This will give you the number 8.

Note that in your case this may not be what you want since it gives a
number, not an integer. This is fine if you know your string contains
a round number, but not if your string can contain a decimal point.
e.g. +'08.5' will give you the number 8.5.

If you ever use this in a calculation of some sort, it's also good to
put parens around your coerce. For example:

var x = something + (+'08') + whatever;

Cheers,
Andy

--
Andrew Chilton
e: chi...@appsattic.com
w: http://www.appsattic.com/

Murvin Lai

unread,
Feb 21, 2012, 5:28:26 PM2/21/12
to nod...@googlegroups.com
proper use of parseInt is do that. parseInt(number, 10)  for 10-base.

Louis Santillan

unread,
Feb 21, 2012, 8:10:02 PM2/21/12
to nod...@googlegroups.com
Thomas Fuchs recommends using double tilda (~~) for string conversion. Safer and just as fast (http://mir.aculo.us/2010/05/12/adventures-in-javascript-number-parsing/).

-L


--
Sent from Gmail Mobile

Marcel Laverdet

unread,
Feb 21, 2012, 8:39:26 PM2/21/12
to nod...@googlegroups.com
I just use Number() [note, no `new` ctor]. No idiomatic operator soup, just an expressive conversion. Floats are preserved.

> Number('08') === 8
true
> Number('1.2') === 1.2
true

Mark Hahn

unread,
Feb 21, 2012, 8:46:23 PM2/21/12
to nod...@googlegroups.com
I just use Number() 

Doesn't + do the same thing?  I'm a lazy typist.

Marcel Laverdet

unread,
Feb 21, 2012, 8:56:38 PM2/21/12
to nod...@googlegroups.com
Yeah it's identical to prefix +, just more "english" and doesn't blend in with string concatenation. It's totally a matter of preference. I personally find that while writing software I'm rarely blocked by raw typing speed so I use Number() because it makes +'s less ambiguous when I'm reading my code later.

On Tue, Feb 21, 2012 at 7:46 PM, Mark Hahn <ma...@hahnca.com> wrote:
I just use Number() 

Doesn't + do the same thing?  I'm a lazy typist.

Mark Hahn

unread,
Feb 21, 2012, 10:06:30 PM2/21/12
to nod...@googlegroups.com
I use pluses without a space so it is quite readable.  +a means parseInt.  + a means there is concatenation or addition going on somewhere.  It is quite intuitive.

Marco Rogers

unread,
Feb 22, 2012, 2:28:17 AM2/22/12
to nod...@googlegroups.com
I use parseInt and always specify the radix. The Number constructor used as a cast does something totally different. Neither will always do what you want. But if you're looking for an integer from a string, and you don't even control it enough to be sure it doesn't have a "0" at the beginning, parseInt with a radix of 10 is 99% what you want.

:Marco


On Tuesday, February 21, 2012 7:06:30 PM UTC-8, Mark Hahn wrote:
I use pluses without a space so it is quite readable.  +a means parseInt.  + a means there is concatenation or addition going on somewhere.  It is quite intuitive.

On Tue, Feb 21, 2012 at 5:56 PM, Marcel Laverdet <mar...@laverdet.com> wrote:
Yeah it's identical to prefix +, just more "english" and doesn't blend in with string concatenation. It's totally a matter of preference. I personally find that while writing software I'm rarely blocked by raw typing speed so I use Number() because it makes +'s less ambiguous when I'm reading my code later.

On Tue, Feb 21, 2012 at 7:46 PM, Mark Hahn <ma...@hahnca.com> wrote:
I just use Number() 

Doesn't + do the same thing?  I'm a lazy typist.

--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to

For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to

Mark Hahn

unread,
Feb 22, 2012, 2:56:25 AM2/22/12
to nod...@googlegroups.com
>  Neither will always do what you want.

The plus sign always does what I want.  It always converts in base 10 and works with integers and floats.

     +"123"    => 123
     +"0123"  => 123
     +"012.3" => 12.3

It is parseInt that causes the trouble with octal.

Jorge

unread,
Feb 22, 2012, 3:39:26 AM2/22/12
to nod...@googlegroups.com
On Feb 22, 2012, at 8:56 AM, Mark Hahn wrote:
>
>
> The plus sign always does what I want. It always converts in base 10 and works with integers and floats.
>
> +"123" => 123
> +"0123" => 123
> +"012.3" => 12.3

+'123 px'
NaN

parseInt('123 px', 10)
123

--
Jorge.

danp

unread,
Feb 22, 2012, 5:37:20 AM2/22/12
to nodejs
I need minutes for a modulus operation, and the time string is of
format "hh.nn". All methods are working fine:

parseInt( time.substr(-2), 10 )

+time.substr(-2)

~~t.substr(-2)

Number( t.substr(-2) )

Thank you all,
Dan

Lothar Pfeiler

unread,
Feb 22, 2012, 8:02:19 AM2/22/12
to nodejs


On Feb 21, 10:50 pm, Tim Caswell <t...@creationix.com> wrote:
> Actually, according to that mdn page I just linked, ES5 (which V8
> implements) should not try to parse octal mode and in a way it's a bug.

Oh, that's a bummer! Coming from C it's just natural that numbers with
preceding 0 are octal numbers. I always thought of it as a feature.

Well, adding the radix parameter, makes code more readable, anyway.
That jslint (never used it) yells at you, definitely makes sense.


>  But changing the behavior will "break the web" for sites that expect the
> ES3 behavior.  Isn't JavaScript versioning fun?
>
>
>
>
>
>
>
> On Tue, Feb 21, 2012 at 3:46 PM, Tim Caswell <t...@creationix.com> wrote:
> > It's not so much a V8 bug, but an unfortunate feature of JavaScript
> > itself.  Crockford would call this one of the "bad parts".  parseInt()
> > tries to be clever and guess the radix if you don't give it one.  Numbers
> > starting with "0" are assumed to be octal (unless it starts with "0x" of
> > course).
>
> > While it's annoying, it's a good idea to always specify the radix (the
> > second argument to parseInt) when parsing numbers and you know the
> > radix. This is why jslint yells at you if you leave this "optional"
> > argument off.
>
> >https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/...

Jorge

unread,
Feb 22, 2012, 10:40:46 AM2/22/12
to nod...@googlegroups.com
On Feb 22, 2012, at 11:37 AM, danp wrote:
>
>
> +time.substr(-2)
>
> ~~t.substr(-2)

~~"12345678901"
-539222987
--
Jorge.

Mark Hahn

unread,
Feb 22, 2012, 1:18:57 PM2/22/12
to nod...@googlegroups.com
+'123 px'
>  NaN 

And that is exactly correct.  '123 px'  is not a number.   Using that "feature" is worse than trusting type coercion.  I would never trust that in my code, just as I always use === instead of ==.  Well actually I use "is" in coffee, but that is a different subject.

What if your string was accidentally "100%" instead of "100 px"?

You said nothing is right for me.  I'm just pointing out that was an overly broad statement.  Using + instead of parseInt *is* exactly right for me.

If you want to be able to use '010' to represent 8 and '1xyz' to represent 1, then more power to you.  I myself will never use parseInt.  Not only for the behavior but because it takes too much typing, is less succinct and therefore is less readable.

Compare...
    area = +w * +h
To ...       
     area = parseInt(w, 10) * parseInt(h, 10)

Dave Clements

unread,
Feb 22, 2012, 11:17:21 PM2/22/12
to nodejs

+1 for +


:D

Lothar Pfeiler

unread,
Feb 23, 2012, 9:30:51 AM2/23/12
to nodejs
I still wonder, if it's cool to have such a big discussion on how to
convert a string into an integer, or if all the java developers laugh
at us. :-)

dolphin278

unread,
Feb 23, 2012, 9:42:04 AM2/23/12
to nod...@googlegroups.com, nodejs
They are busy with their spaceship-size configuration files, so we safe :)

> --
> Job Board: http://jobs.nodejs.org/
> Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
> You received this message because you are subscribed to the Google
> Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com
> To unsubscribe from this group, send email to

> nodejs+un...@googlegroups.com

Marco Rogers

unread,
Feb 23, 2012, 2:20:33 PM2/23/12
to nod...@googlegroups.com
You guys should stop trolling each other and try to be helpful. This is an area of js fraught with both FUD and wtfjs. Better to educate than to spout personal anecdotes and one off edge cases. Mark has the right idea by saying pick the technique that "does what you want". But you have to know the difference in order to do that. And you can't assume that what you want is what everyone always wants. This is an implementation detail.

And finally don't ignore the most obvious and important difference. parseInt... parses integers! It will always try to give you back an integer. Whatever your value is, you will get an integer or you will get NaN. It will try to do this with improperly formatted strings as long as they start with a parse-able number, e.g. "100px". This is either a nice feature, or something to be avoided, depending on how well you've validated your input. On the other hand, number conversion is part of the standard language grammar. It uses well defined (but not necessarily intuitive) rules to take a value and give you a number that may or may not have a decimal component, or if it can't, it'll give you NaN. But it also respects alternate number formats that are valid like exponential notation, e.g. Number("10e2") === 1000. Using the unary "+" operator in front of a value is strictly equivalent to calling Number().

Now, all of that being said, I think it's clear that both of these violate principle of least surprise once you get into edge cases. They will both screw you at some point or another if you don't control your input and validate your output. So which one you should use isn't an "always" thing and it has nothing do with what you find "more readable". Understand them both, and pick the one that works for what you're doing.

:Marco

Lothar Pfeiler

unread,
Feb 24, 2012, 8:35:39 AM2/24/12
to nodejs
Yes, you're right. I am new to a JS group. So, mixing integers and
floats is a new experience to me. This competition of typing less, was
something I took part in back in the 90s and I thought it's gone
because of the auto completion feature of today's editors. And because
of today's processors and libraries I thought the performance
discussions are gone, too.

I think the dos and don'ts of a language are more important, which
brings me to my question regarding string-to-integer conversion.
Is it ok to extent the String object for some oo-style?

e.g.:
String.prototype.intValue = function () {
return parseInt(this, 10);
};

var area = width.intValue() * height.intValue();

Lothar

Mark Hahn

unread,
Feb 24, 2012, 1:04:04 PM2/24/12
to nod...@googlegroups.com
 This competition of typing less, was something I took part in back in the 90s 

While typing does matter, this is mainly a readability issue.  Low-noise syntax, like coffeescript, is much easier to read. 

Marcel Laverdet

unread,
Feb 24, 2012, 2:37:54 PM2/24/12
to nod...@googlegroups.com
You could extend String.prototype if you wanted to but it's probably one of the less common ways to do this kind of thing. It has disadvantages like portability, and it will ONLY works on strings. Using Number() or + on something that's not a string (undefined, an object, a number) will work fine, but your prototype idea will fail. If you did want to go this way I'd recommend calling it `toNumber` to match the `toString` convention.

--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to

Mark Hahn

unread,
Feb 24, 2012, 2:41:46 PM2/24/12
to nod...@googlegroups.com
You guys should stop trolling each other and try to be helpful.  

I take offense at this.  There is  trolling and there is a fun debate.  Also, I think we each imparted information that would be useful to lurkers.

So in the same spirit as your comment, I'll say "get off your high horse".

Jorge

unread,
Feb 24, 2012, 2:46:58 PM2/24/12
to nod...@googlegroups.com
On Feb 24, 2012, at 8:37 PM, Marcel Laverdet wrote:

> You could extend String.prototype if you wanted to but it's probably one of the less common ways to do this kind of thing. It has disadvantages like portability, and it will ONLY works on strings. Using Number() or + on something that's not a string (undefined, an object, a number) will work fine, but your prototype idea will fail. If you did want to go this way I'd recommend calling it `toNumber` to match the `toString` convention.

String.prototype.toInt= function toInt () { return parseInt(this, 10) };
"123 px".toInt()
123
--
Jorge.

Marcel Laverdet

unread,
Feb 24, 2012, 3:47:17 PM2/24/12
to nod...@googlegroups.com
So? That's nothing we haven't covered here. Personally I'd recommend:
String.prototype.toNumber = function() { return Number(this) };

Actually I wouldn't recommend it, I'd recommend just using Number() or + without touching the prototype.

Lothar Pfeiler

unread,
Feb 27, 2012, 4:25:23 AM2/27/12
to nodejs
Maybe I don't get it, but how can I force Number() to give me an
Integer? parseInt('2.3') will give me an integer. Number('2.3') will
give me a float.

Once, I gave my students the task to calculate the quarter of the
year. With a type strict compiler language like C the algorithm is
pretty simple: date.getMonth() / 3 + 1.
Because they were not thinking of integers it was tough for them to
figure out the algorithm. Sometimes you just need integers.
parseInt(date.getMonth() / 3, 10) + 1.

Plus, I thought this is a discussion about parseInt().

Ryan Schmidt

unread,
Feb 27, 2012, 10:49:43 AM2/27/12
to nod...@googlegroups.com

On Feb 27, 2012, at 03:25, Lothar Pfeiler wrote:

> Maybe I don't get it, but how can I force Number() to give me an
> Integer? parseInt('2.3') will give me an integer. Number('2.3') will
> give me a float.
>
> Once, I gave my students the task to calculate the quarter of the
> year. With a type strict compiler language like C the algorithm is
> pretty simple: date.getMonth() / 3 + 1.
> Because they were not thinking of integers it was tough for them to
> figure out the algorithm. Sometimes you just need integers.
> parseInt(date.getMonth() / 3, 10) + 1.
>
> Plus, I thought this is a discussion about parseInt().

This discussion was initially a bug report about parseInt(), and quickly became an explanation of why it's not a bug and is instead behaving as designed, though clearly not as many people anticipate; this may mean it was not designed well.

By what algorithm would you like to convert a floating point number to an integer? There are several methods available to you, including Math.round(), Math.floor() and Math.ceil().

parseInt() is about converting a string representing an integer, in any of several formats including hex, octal and decimal, to a JavaScript integer; date.getMonth() / 3 is not a string and furthermore does not represent an integer so to me there's no reason to use parseInt() on it; just run the math function on it that you intend. For example if you mean to discard anything after the decimal point, maybe you want Math.floor().

Mark Hahn

unread,
Feb 27, 2012, 1:36:15 PM2/27/12
to nod...@googlegroups.com
I always use  Math.round(), Math.floor() and Math.ceil().  Trusting anything else taxes my memory and is less readable.

 

Lothar Pfeiler

unread,
Feb 28, 2012, 12:20:52 AM2/28/12
to nodejs
Well, just wanted to point out, that you shouldn't mix parseInt() and
parseFloat(). That JavaScript lacks of integer calculation is a pity,
but every language's got its downsides.
Reply all
Reply to author
Forward
0 new messages