Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2010 (Landsdown, VA) with: Brian Swartzfager and Simon Free and Jason Dean and Jim Priest and Vicky Ryder

Exploring Javascript's parseInt() And parseFloat() Functions

By Ben Nadel on

The other day, I happen to look up the documentation for Javascript's parseInt() function and was surprised to see that the function did way more than I thought it did. Not only can it parse strings into numeric data types, it can also parse numeric-strings of different bases (ex. base2, base10, base16). You can define a base as part of the function call; or, you can allow the Javascript engine to guess the base according to the incoming string format. In any case, I thought I would take a moment to demonstrate both the parseInt() and parseFloat() functions in case anyone else was unaware of their full potential.

Javascript's parseInt() function takes a string and returns an integer (base10 integer). When executing this parsing and data type conversion, the parseInt() function can take the following two signatures:

  • parseInt( string )
  • parseInt( string, base )

In the latter signature, the "Base" argument can be any number between 2 and 36. In the former signature, where no base is provided, the Javascript engine will chose the most appropriate base according to the incoming string format. In most cases, the base is assumed to be 10 (decimal). However, there are two cases in which the implied base is not 10:

  • Strings that start with "0x" are assumed to be base16 (hexadecimal).
  • Strings that start with "0" are assumed to be base8 (octal).

When parsing a string into a numeric data type, the parseInt() function will start from the left and parse characters until it runs out of numeric data - the rest of the string will be ignored. Let's see this in action:

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Exploring parseInt() and parseFloat()</title>
  • <script type="text/javascript">
  •  
  • // ParseInt() will start parsing string characters, in order
  • // to make a valid numeric data type. If you do not provide
  • // an incoming number system, it will be assumed to be
  • // base-10.... most of the time.
  • //
  • // NOTE: Numbers starting with 0x will be parsed as base16.
  • // NOTE: Numbers starting with 0 wlil be parsed as base8.
  • console.log( "123: ", parseInt( "123" ) );
  • console.log( "123.456: ", parseInt( "123.456" ) );
  • console.log( "+123.456: ", parseInt( "+123.456" ) );
  • console.log( "-123.456: ", parseInt( "-123.456" ) );
  • console.log( "123ABC: ", parseInt( "123ABC" ) );
  • console.log( "ABC: ", parseInt( "ABC" ) );
  • console.log( "5px 5px: ", parseInt( "5px 5px" ) );
  • console.log( "(123): ", parseInt( "(123)" ) );
  • console.log( "0xF: ", parseInt( "0xF" ) );
  • console.log( "012: ", parseInt( "012" ) );
  • console.log( " 123 : ", parseInt( " 123 " ) );
  •  
  • console.log( "---------------------------------------" );
  • console.log( "Explicit Base 10:" );
  • console.log( "---------------------------------------" );
  •  
  • console.log( "123: ", parseInt( "123", 10 ) );
  • console.log( "123.456: ", parseInt( "123.456", 10 ) );
  • console.log( "+123.456: ", parseInt( "+123.456", 10 ) );
  • console.log( "-123.456: ", parseInt( "-123.456", 10 ) );
  • console.log( "123ABC: ", parseInt( "123ABC", 10 ) );
  • console.log( "ABC: ", parseInt( "ABC", 10 ) );
  • console.log( "5px 5px: ", parseInt( "5px 5px", 10 ) );
  • console.log( "(123): ", parseInt( "(123)", 10 ) );
  • console.log( "0xF: ", parseInt( "0xF", 10 ) );
  • console.log( "012: ", parseInt( "012", 10 ) );
  • console.log( " 123 : ", parseInt( " 123 ", 10 ) );
  •  
  • console.log( "---------------------------------------" );
  • console.log( "Explicit Base 16:" );
  • console.log( "---------------------------------------" );
  •  
  • console.log( "123: ", parseInt( "123", 16 ) );
  • console.log( "123.456: ", parseInt( "123.456", 16 ) );
  • console.log( "+123.456: ", parseInt( "+123.456", 16 ) );
  • console.log( "-123.456: ", parseInt( "-123.456", 16 ) );
  • console.log( "123ABC: ", parseInt( "123ABC", 16 ) );
  • console.log( "ABC: ", parseInt( "ABC", 16 ) );
  • console.log( "5px 5px: ", parseInt( "5px 5px", 16 ) );
  • console.log( "(123): ", parseInt( "(123)", 16 ) );
  • console.log( "0xF: ", parseInt( "0xF", 16 ) );
  • console.log( "012: ", parseInt( "012", 16 ) );
  • console.log( " 123 : ", parseInt( " 123 ", 16 ) );
  •  
  • </script>
  • </head>
  • <body>
  • <!-- Intentionally left blank. -->
  • </body>
  • </html>

As you can see here, I am running this in three separate blocks. The first block lets the parseInt() function determine the most appropriate base on its own. The second and third blocks explicitly supply the base along with the parseInt() function calls. When we run the above code, we get the following console output:

123: 123
123.456: 123
+123.456: 123
-123.456: -123
123ABC: 123
ABC: NaN
5px 5px: 5
(123): NaN
0xF: 15
012: 10
123 : 123
---------------------------------------
Explicit Base 10:
---------------------------------------
123: 123
123.456: 123
+123.456: 123
-123.456: -123
123ABC: 123
ABC: NaN
5px 5px: 5
(123): NaN
0xF: 0
012: 12
123 : 123
---------------------------------------
Explicit Base 16:
---------------------------------------
123: 291
123.456: 291
+123.456: 291
-123.456: -291
123ABC: 1194684
ABC: 2748
5px 5px: 5
(123): NaN
0xF: 15
012: 18
123 : 291

This is pretty cool stuff! To me, there are two important take-aways from this demonstration:

  1. You can use different bases when parsing numeric string data.
  2. Any non-numeric information places after the numeric data within the incoming string is ignored.

Javascript's parseFloat() function is not quite as robust as the parseInt() function. It parses the incoming string into a floating point number rather than a decimal; but, it can only work with incoming values in base10 (decimal values). In other respects, it works much the same as parseInt(). Let's take a look at some code:

  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Exploring parseInt() and parseFloat()</title>
  • <script type="text/javascript">
  •  
  • // ParseFloat() will start parsing string characters, in order
  • // to make a valid numeric data type.
  • //
  • // NOTE: Unlike parseInt(), parseFloat() only works with
  • // incoming strings in base10 (decimal).
  • console.log( "123: ", parseFloat( "123" ) );
  • console.log( "123.456: ", parseFloat( "123.456" ) );
  • console.log( "+123.456: ", parseFloat( "+123.456" ) );
  • console.log( "-123.456: ", parseFloat( "-123.456" ) );
  • console.log( "123ABC: ", parseFloat( "123ABC" ) );
  • console.log( "ABC: ", parseFloat( "ABC" ) );
  • console.log( "5px 5px: ", parseFloat( "5px 5px" ) );
  • console.log( "(123): ", parseFloat( "(123)" ) );
  • console.log( "0xF: ", parseFloat( "0xF" ) );
  • console.log( "012: ", parseFloat( "012" ) );
  • console.log( " 123 : ", parseFloat( " 123 " ) );
  •  
  • </script>
  • </head>
  • <body>
  • <!-- Intentionally left blank. -->
  • </body>
  • </html>

As you can see, we're basically re-using the first demo from the parseInt() code and just swapping parseInt() with parseFloat(). When we run the above code, we get the following console output:

123: 123
123.456: 123.456
+123.456: 123.456
-123.456: -123.456
123ABC: 123
ABC: NaN
5px 5px: 5
(123): NaN
0xF: 0
012: 12
123 : 123

Other than not treating "0x" as base16 or "012" as base8, the only significant difference is that parseFloat() returns decimals for values like "123.456" where as parseInt() would just return 123.

I know this is a fairly basic exploration; but, these functions (parseInt() specifically) do a bit more than I thought they were capable of doing so I figured I'd pass that information along to anyone else who didn't know.




Reader Comments

Can you remember a world before console.log()? How did we all not go insane from alert() overload?

Reply to this Comment

@Rick,

A little while ago, I was in a world where there was NO console.log()... and then I was attacked by a bear before briefly morphing into Steve Carell for a fight scene.... luckily, this all turned out to be a dream and when I woke up, console.log() was very much real.

Reply to this Comment

If you're just now learning this, you must not be LINTing your code. ;)

LINT requires you pass the second param to avoid code bugs which can pop up when you let JS guess the base.

Reply to this Comment

I have been falling into the trap of parseInt as well. It was quite surprising to find out that base 10 is not the standard behavior unless you tell the function otherwise.

Thanks for pointing it out to the masses!

Reply to this Comment

Ben,

Great post. I wish I would have read through this about 2 weeks ago as the parseInt() function broke part of my code (bad code on my part). It was hard to narrow down, but after looking in depth at parseInt(), I realized that parsing a string like "09" returns a very different value when not specifying base 10. I think the other part of my code discovered an oddity with IE browsers...

http://markdross.wordpress.com/2010/09/04/internet-explorer-oddity-when-referencing-strings-in-javascript/

Anyway, thanks for the post. It's helpful to read and re-read to make sure I don't make the same mistake again.

Reply to this Comment

Mark,

It is for that exact reason the the LINT (mentioned above) requires parseInt() always be given the radix parameter.

Jim

Reply to this Comment

@Jim,

LINT sounds cool. I'll have to check it out then - I like the idea of not having potential bugs creeping up in different contexts.

Reply to this Comment

@Ben
+1 for JSLint. As @Jim points out, it helps to avoid common JS issues. It's based on Douglas Crockford's JS style guide, a dude who knows a thing or two about JS.

There's a java powered CLI version as well, with an Ant taks (If you're using Ant in your build process, it's great to ensure you're not checking in crappy JS code).

http://code.google.com/p/jslint4java/

Reply to this Comment

Ben,

JSLINT.com and JSONlint.com have saved me hours of programming problems. Check them out when you can,

Reply to this Comment

I'm surprised that parseInt() will attempt to parse in base8 when the string has a leading 0. I gotta remember to remove them before using parseInt() next time. It also does the same when there are multilpe leading zeros, like "000012".

Reply to this Comment

@Vinh,

No need to strip leading zeros, just give parseInt() the radix param telling it to use base10.

Reply to this Comment

The omitted radix bit us a while back with debit card expiration data validation. It worked for every month except August and September ("08", "09") where the leading zero created octal literals and the "8" and "9" were treated as invalid characters.
(This is the same behavior as C's atoi)

These numbers parsed as octal "0"

Reply to this Comment

A faster and simpler way of converting float number to integer is using bitwise operators:

~~2.395 //return 2

OR

2.395 >> 0 //return 2

And it's faster than parseInt.

Reply to this Comment

@Acaz,

That's some clever stuff (I am not too familiar with the tilda operator - I looked into it once, but have since forgotten what it does).

That said, the use of parseInt() is not to convert floats to ints; it's to parse numeric data out of string data (and string data containing values with arbitrary bases). I don't think you can substitute such use cases with bit-wise operations.

Reply to this Comment

@Ben

The best way is to use (value-0) instead of parseInt. parseInt() is almost always the wrong tool for the job.

The only use cases I can think of that makes sense is when you want to parse a string with the unit attached or a number not in base 10 (which is very rare).

parseInt("22km",10) // this is a real use case
parseInt("09",10) // this is wrong, you wanted -0 instead

All the bugs mentioned in this thread, like the one from Jon, would have been prevented by using -0.

It's like using isDefined() in ColdFusion. Chances are you meant to use structKeyExists().

Reply to this Comment

@Elliott,

It took me a second to figure out what you meant by (value-0) - I thought that was an algorithm name or something :) I've used similar things in the past: (value*1).

But I agree, the place I've most used parseInt() is when dealing with strings that have a "px" or the line attached to it.

Reply to this Comment

Post A Comment

?
You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.