JavaScript and Floating Points Arithmetics

We (i.e. anyone who has played with JavaScript) all have heard something about how floating points are tricky and borderline impossible to deal with. While this is not exclusive to JS, it is worth knowing a thing or two behind the limitations of dealing with floating numbers.

Let’s start with a well known example:

var a = 0.1 + 0.2;
a === 0.3;   // false
console.log(a);   //0.30000000000000004

The only way to deal with this is to use the toFixed() property from the Number object or to convert everything into integers, perform the calculations then convert everything back into decimals. Both methods are not guaranteed to produce the correct result, especially when dealing with complex calculations with various floating point variables.

I found out the best way to understand floating point problems is to use the decimal system most humans are so used to. Try expressing 1/3 in a decimal system in the best way possible. There is literally no way to express it to its precision. There are hacks, like 0.333... repeating, but these are all ways that confirm our lack of expressing 1/3 in decimal. Something similar is happening with JavaScript and floating points.

Anyone who has taken an intro class in Calculus will be familiar with the Zeno’s paradox. To summarize it, 1 + 1/2 + 1/4 + 1/8 + .... will always approach 2 but never be equal to 2. This is because we are always halving our distance from 2. That is exactly what is going on when JavaScript tries to express some floating points.

Consider this Binary code:

Integers:
Binary: 1 => Decimal: 1
Binary: 10 => Decimal: 2
Binary: 1101 => Decimal: 13

Floating points:
Binary: 0.1 => Decimal: 0.5
Binary: 0.0101 => Decimal: 0.3125
Binary: 0.00011001 => Decimal: 0.09765625
Binary: 0.00011001100110011 => Decimal: 0.09999847412109375

As you can see from above, the binary value is getting closer and close to 0.1 (in Decimal) but never actually equals it. It is a shortcoming of expressing certain floating points in binary; in the same way we can never fully express certain floating points (e.g: 1/3) in decimal. You can try this with pretty much any base system (try expressing 0.1 (decimal) in Base 3).

To answer our original issue (i.e. 0.1 + 0.2), calculations are usually transformed into binary, evaluated then converted back into decimal. With its 32-bit limitation, the expression is limited to only 32 floating points. It then becomes:

0.00011001100110011001100110011001 //approx. of 0.1
+ 
0.00110011001100110011001100110011 //approx. of 0.2
__________________________________

0.01001100110011001100110011001100 //the actual result in binary to be converted into decimal

Want to try something even more fun?

for(var i = 0, x= 0; i<10;i++){
  x += 0.1;  //increment x by 0.1 ten times
}

console.log(x); //0.9999999999999999

PS: I should emphasize that this isn’t something that is unique to JavaScript. Most languages by default have this issue. I just used JavaScript because it’s the most comfortable/easy language to express the idea.

Advertisements

One Year Later

Twenty-nine posts in and it has been one year since I started running this blog. To be honest I thought I would have given up on it after several weeks. However, the page views have been somewhat surprising and encouraging. The responses have been enough to push me to publicize some of my projects. Henceforth, I will try to summarize some of the projects I have been involved with in the past year.

UK Football League Stats: This is my latest project (as of Jan 8th, 2014), and surprisingly expeditious. Coming from a stats background, I have always been keen on learning d3js, and this was the perfect opportunity to infuse the library with football and statistics. A testament to my vibrant social life, I churned out the first working draft on New Year’s eve. It scraps up-to-date csv data from Football Data’s website using php, processes and displays the data using d3, and finally adds interactivity on the tables using datasorter and DataTable jQuery plugins. Despite its short turnaround time, I have learnt the most from it. I started with hosting the csv data on my server (manually uploading the files), only to realize I would need a better solution to make sure the data is always up-to-date. This prompted me to learn some basic web-scrapping and their limitations (mostly CORS related). The project alone has inspired me to learn more on web-data scrapping.

SoundBum: One of my longest running projects; it uses Soundcloud’s API to play random music from any genre. I got the idea from working on CodeAcademy’s Soundcloud API tutorial. Previously, it had a pretty basic functionality. It prompted you for a genre, and returned a random song. In the last month or so, I decided to make it slightly more interesting. It can now auto-load a new song whenever the current one ends. This was a tricky hack which led me to learn about iframe’s sandbox attribute and foreign API limitations. It is also the only app I actually use on a daily basis. Future versions might include a better UI (currently it only has an input, button and an iframe) but I am not sure of the direction yet.

GIF to Canvas: In my desperate attempt to play the JS/HTML5 game like all these hipsters, I created a simple animation with playback controls. If possible, I might include some web-scrapping to create these animations by automating the entire process.

Guess the Number: A simple game that employs Binary Search Algorithm. It uses basic jQuery and CSS. It is an UI improvement on a previous implementation.

There are many more smaller JavaScript challenges I have worked on, but they are more of 30 min challenges I use to brush up on my knowledge (and learn new interesting tid bits). These tend to inspire me to write tech related posts.

In the next year, I am hoping to become more collaborative in my coding. The other day, I had my first pull request accepted. It felt strange yet exciting directly contributing to an open-source project, despite it being a 3-line code update. Hopefully many more to come. Here’s to another year!