Exploring Javascript's parseInt() And parseFloat() Functions
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:
- You can use different bases when parsing numeric string data.
- 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.
Want to use code from this post? Check out the license.
Reader Comments
Can you remember a world before console.log()? How did we all not go insane from alert() overload?
@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.
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.
@Jim,
What is Lint? Is that a one of the test-driven frameworks?
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!
Ben,
JSLint ( http://www.jslint.com/ ) is a static code analysis ( http://en.wikipedia.org/wiki/Static_code_analysis ) tool written and maintained by Douglas Crockford.
It is GREAT for avoiding issues common to JS as well as finding bugs when all other debugging efforts have failed.
I even have a Node.js powered CLI version :)
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.
Mark,
It is for that exact reason the the LINT (mentioned above) requires parseInt() always be given the radix parameter.
Jim
@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.
@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/
Ben,
JSLINT.com and JSONlint.com have saved me hours of programming problems. Check them out when you can,
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".
@Vinh,
No need to strip leading zeros, just give parseInt() the radix param telling it to use base10.
@Jim
That's a lot simpler. Thanks :-)
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"
Yeah, I've definitely learned my lesson to just always provide the radix :)
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.
@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.
@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().
@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.
very useful and well explained.
thanks!
//I NEED HELP ABOUT SWITCH STATEMENT
<HTML>
<HEAD>
<script>
function zaba(){
var number1st;
var number1st = prompt("Please enter drill size or number","") ;
number1st = parseFloat(number1st);
switch (number1st) {
// it work properly
case (80):
alert (" answer is 0.0135" );
break;
// it work properly
case (0.5):
alert (" answer is 0.5 " );
break;
// why do not work properly
case (1/2):
alert (" answer is 0.5 " );
break;
// why do not work properly
case (A):
alert (" answer is 0.350 " );
break;
// why do not work properly
case (b):
alert (" answer is 0.450" );
break;
if (number1st != null && number1st != "")
{
return number1st;
}
}
}
</script>
</HEAD>
<BODY>
<input type="radio" name="radio1" value="two" onclick="zaba()">one
<input type="radio" name="radio1" value="three" onclick="zaba()">two
<input type="hidden" name="hidden1" value="name">
</BODY>
</HTML>