debuggable

 
Contact Us
 

7 + 8 === 7 in JavaScript

Posted on 6/10/09 by Felix Geisendörfer

I kid you not, this is an issue I actually ran into a long time ago and have been terribly careful of avoiding ever since.

It must have been a fantastic day in the "Bad Parts" JavaScript department. While one team was busy screwing up the + operator to be responsible for both string concatenation and addition, another team set out to build a nasty trap inside the parseInt() function.

This together results in probably my favourite JavaScript bug of all times. It goes like this: You have two strings that contain zero padded numbers (like hours or minutes) and you want to perform some math on them:

var a = '07';
var b = '08'

alert(a + b);

Of course you would not write such code, but maybe you have a friend who has done it. This friend probably quickly realized that '0708' was not the result he was hoping for, so he got clever and updated his code to:

var a = '07';
var b = '08'

alert(parseInt(a) + parseInt(b));

However, it turns out that the result of this operation is actually 7. SEVEN you ask? Yes: it's not a bug, it's a feature.

JavaScript assumes that any 0-prefixed string ought to be referring to an octal number. This will not become apparent until your string represents an invalid octal such as '08'. So in order to outsmart this "feature" you have to explicitly provide the base for your integer:

var a = '07';
var b = '08'

alert(parseInt(a, 10) + parseInt(b, 10));

I hope this will one day safe somebody the hour of my life that went into this : ).

-- Felix Geisendörfer aka the_undefined

PS: Got a great JavaScript bug like this as well? I'd be happy to hear about it in the comments.

 
&nsbp;

You can skip to the end and add a comment.

Simon Brüchner said on Oct 06, 2009:

Too late, just ran into this problem/feature last week. Took me 1/2 hour.

robust solution  said on Oct 06, 2009:

nice tip.
thank you

for the moment I do not remember any tip, although I found many in my professional career.

yed_ said on Oct 06, 2009:

Hi,

for last half year I was developing some economic software. There were lot of number operations in JS and I went nuts. Final solution for working with numbers in JS was multiply every variable with 1. For example:

var a = '07';
var b = '08';

alert( a*1 + b*1); //15

It's not nice solution, but it solved all my problems.

I found also some bugs in JS calculation, for example in firefox 100 * 1.15 = 114.999999999

(sorry my english)

Aeron said on Oct 06, 2009:

Definintely recommend using a Javascript framework. Mootools has great helpers.

For example you have parseInt(), parseFloat() but then toFixed(). MT does a great job of normalizing this:
toInt() with toFloat() - which of course also sets a base 10 radix and allows for better chaining all-in-one!

Gordon  said on Oct 06, 2009:

I frequently encounter calculation errors where X multiplied by ten will result in 10X-0.000000001 or similar, so 10*5 = 49.999999999 or 5^2 will return 24.9999999.

Gabriel  said on Oct 07, 2009:

About the decimal glitch, I remember seen a script wich split the numbers in decimal and integer parts and perform the multiplicaction separately and join the numbers after that.

PS1: I just discover the rickrollbug! :D
PS2: Sorry by my english

xtrementl  said on Oct 07, 2009:

You could instead use Number() instead of parseInt().

Tim Koschützki said on Oct 07, 2009:

Posted for David Thalmann:

@yed: This is not a "bug" of JavaScript, it's just the IEEE-Standard for floating-point operations (correctly applied by JavaScript), check this:

var i = 0.1;
var j = 0.2;

alert(i+j);

To "see" what actually happens, see here: http://bit.ly/2r9Be

@topic: Good post, but I think on every programming language you have to keep attention when dealing with numbers (often combined with casting and other "features").

Java: System.out.println((int) 2.5 * 2.0 + (int) (2.5 * 2.0));
PHP: if (1 == "2") echo "woot";

Javi  said on Oct 07, 2009:

Yep, same happened to me two months ago. We had a calendar applet, based on jQuery UI datepicker.

It worked fine for nine months. But when august came, clients started to call saying the applet was not displaying the right date anymore. After a couple of hours, I found this "bug" and realized that august is the eighth month!

Łukasz said on Oct 07, 2009:

Recently I found one really annoying thing in JS (it's not related to Math/parseInt/etc) but I lost few hours wondering 'why?'
var d = new Date(2009, 08, 02);

You'd expect that 'd' will store the info about 2nd of August of 2009.

No.

It's 2nd of JULY

Here's why: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date

Felix Geisendörfer said on Oct 07, 2009:

Łukasz: Haha, so month is 0-11 but date is 1-31. Pure genius : ).

Javi  said on Oct 07, 2009:

@Łukasz: Exactly! Now I remember why I had to do "parseInt(month) - 1", but didn't have to do the same thing with the day. So that's why it worked on february the 8th but didn't on august the 2nd.

And all this work just to display a date!

Chris  said on Oct 07, 2009:

>>> typeof NaN
"number"

this is also a bit odd :-)

Gordon  said on Oct 07, 2009:

var d = new Date(2009, 08, 02);
You'd expect that 'd' will store the info about 2nd of August of 2009.

No.

It's 2nd of JULY

Try September :)
0 Jan 1 Feb 2 Mar 3 Apr 4 May 5 Jun 6 Jul 7 Aug 8 Sep 9 Oct 10 Nov 11 Dec

Łukasz said on Oct 07, 2009:

@Gordon - well, I fixed it with (month+1) just to keep my sanity safe :-)

NOSLOW  said on Oct 07, 2009:

JSlint.com has saved me from this bug. Otherwise, it would have bitten me (eventually).

Simon Brüchner said on Oct 07, 2009:

@NOSLOW: How did jslint saved you? Did you cecked your script with it or did you used it as a framework?

Lukasz  said on Oct 07, 2009:

@Simon - jslint is a great validation/optimizer tool created by Doug Crockford. If you develop in JS *you have to use it*. by deafult it warns you about such 'gotchas' as parseInt without decimal base, ++ and -- operators.

NOSLOW  said on Oct 08, 2009:

@Simon: Lukasz summed it up. JSlint warns you whenever you use javascript's "bad parts". After using it a while, you'll see that it does a good job at catching things that need to be corrected.

Tom  said on Oct 08, 2009:

Yes, nice post, thanks.
I've found an interestning problem too:

Never name your function parameter 'class'.
I've spent 1 hour to find out what the problem is. At the end I commented out everything except the problematic method header, and then I found it.

In firefox, it is ok. but in ie6 no error is displayed, but your script not working anymore (found it with putting alert('') calls after the problematic declaration).

Br,
Tom

Simon Brüchner said on Oct 08, 2009:

Another great time waster that keeps me from my work is a comma "," in an array/object AFTER the last entry. FF eats it, IE not.

Felix Geisendörfer said on Oct 08, 2009:

Tom: You need be even more careful with reserved keywords in Safari, it will even refuse to take those that are not being used by JS yet.

Simon Brüchner: Yeah, that's usually the first thing I have to fix when making my sites IE compatible : )

Tom  said on Oct 08, 2009:

Thanks for the information, I skipped the test on safari this time.

Hard times today because of ie6... :S
Maybe you are all familiar with this bug (or feature, I don't know), but it's new for me and it's really annoying.

I have a radio button group, and a js onchange handler.
Simple, isn't it?

It works ok in ff, but in ie, the action of onchange event fired just after focus lost on that element.

I don't know the working in other browsers, but I bet they have no problem with onchange handling.

As a solution I use the onclick event from now.

Tom

Łukasz said on Oct 08, 2009:

@Simon and Felix - JSlint warns about the trailing comma after last element of an array/object as well :-)

Andrew Kolesnikov said on Oct 08, 2009:

Using Javascript with JSlint has saved me countless hours. Is there a bundle for TextMate to validate JS with JSlint?

Łukasz  said on Oct 08, 2009:

@Andrew - yup, there's a bundle for Textmate (and E) and since JSlint is a command line tool it can be used with any decent editor/ide

Bruno Cassol said on Oct 08, 2009:

Just one thing: RTFM!

Even my 14 yr sister knows that in computers numbers starting with 0 are on octal notation. ECMAScript specification says so too.

Felix Geisendörfer said on Oct 08, 2009:

Bruno Cassol: Yeah, I have read it and it says you are encouraged to not be a smart ass and leave octals alone. Have you read it?

Paul Sayre said on Oct 08, 2009:

My favorite is that you can overwrite undefined and null.
var a;

alert(a == undefined); // true

undefined = 3;

alert(a == undefined); // false

Enrique Jacobs said on Oct 09, 2009:

I read this blog post two days ago and now I ran into exactly the same problem when parsing a date time value (actually I develop with JS since a long time and I can't remember running into the octet pitfall up to now).
Saved me some time, thanks!

BTW: Have a look at our quiet new CakePHP-driven community app: http://www.guerra-creativa.com

Guaranteed to be bug-pestered ;-)

Tim Koschützki said on Oct 10, 2009:

@Enrique Jacobs: Very cool design!

jaywink said on Oct 10, 2009:

Javascript is odd at times :) just recently learned that foo['bar'] is not an associative array but actually just a property (ie foo.bar) :P

http://www.basshero.org/61/javascript-arraylength-fails-if-key-has-line-breaks/

(which isn't true but after writing that post I was told javascript has no associative arrays)

Bret Kuhns  said on Oct 11, 2009:

Yeah, this Octal notation is nothing new, though I can see why it's not intuitively obvious when you first hit this "error". PHP uses the same convention http://us3.php.net/manual/en/language.types.integer.php

$a = 0123; // octal number (equivalent to 83 decimal)

Despite this, though I haven't tried, I have a feeling doing $var = (int)"08"; in PHP will probably give you a decimal 8 int.

KKovacs said on Oct 17, 2009:

Felix,

It's not just in JavaScript. Starting a number with a zero means octal in several languages, including C, Python, PHP and TCL (those I know of, maybe others, too). :)

This post is too old. We do not allow comments here anymore in order to fight spam. If you have real feedback or questions for the post, please contact us.