Learning about some IEEE-754 behavior!

Foreword: This is not an attack on JavaScript. After talking with people, this is just the behavior of IEEE-754. I knew what floating point numbers were - limited precision decimals - but nothing past that. For some reason while writing this and playing around it just didn't occur to me that's what was happening.

Personal study can be a lot of fun. Lately Mathematics has been the subject of study for me. Before that was Electronics. Everyone who says "you don't need Math to program" is technically right but practically wrong. Math is very general, which means while I learn new concepts there are so many places I can apply them afterwards - this is my primary motivation. The secondary motivation is learning at a different level of abstraction.

What's the best way to start personal study? I started with Khan Academy. While it's great, Khan Academy feels like there is something missing...An introduction to Mathematics maybe? Something that takes a glimpse into the abstract mind of a Mathematician, not a Software Developer. Mathematics: A Very Short Introduction was the window into that brain. Not only is it true to its name, the author explains very well what goes on. There was some initial hesitation about buying it at first, but after I read the reviews on Google Books, I was sold, and bought it for $7. Google Books is the most impressive ebook service I've used, but we won't get into that. Lets get to some JavaScript.

In Chapter 4: Limits and infinity, the reader learns the truth about infinity: it's just another object in the Mathematics world. There is no need to reason about what infinity is. The important question is what does infinity do for us, as a Mathematician? From my point of view (and this has zero value) it lets us know there are sequences that never end. It also lets us know that infinitely repeating zeros or nines usually cause a number to round up or down. JavaScript's idea of infinity is what's broken here. My understanding of what happens in these situations is what's broken here.

Take the rational number 1/3. We all know 1/3 = 0.3... repeating. We also know if we 1/3 * 3, we get 1. Multiplication is really just addition many times. This means 1/3 * 3 is the same as 0.3... + 0.3... + 0.3... , which would appear to be 0.9... repeating. What the heck, right? It isn't though, because the "very last decimal 9" would cause a carry over, making the answer 1 too. Obviously we would never reach it, but in theory it could happen and should happen because our fractional representation gives us the correct result. What's happening is our decimal representation is limiting the representation.

Then we take the awesome sqrt(2). Again sqrt(2) is just another Mathematical object that has a decimal representation we can never fully see. Representing that number as sqrt(2) is more accurate, or maybe this is easier to reason about: x² = 2. Anyways, if you start finding numbers that satisfy x, you will see when you multiply them together you get 1.9... . You will never reach 2, which doesn't make sense, because there is an answer - we just can't represent it with decimals. That answer is simply sqrt(2). When you multiply sqrt(2) twice (aka to the power of 2), the answer is 2. In JavaScript (and any language using IEEE-754 decimals) this isn't the case.

Open up the developer console in your web browser.

Now type in 1/3, and you'll see 0.333333333333333, as expected. Now type in 1/3 + 1/3. You should get 0.666666666666, as expected...But now type in 1/3 + 1/3 + 1/3. Hit enter. Woah. What is going on here? Why didn't we get 0.999999999999? I honestly have no idea why, but was pleased to see the correct answer. This holds true for any fraction.

So if that gives the right answer, we'd expect sqrt(2)² to give the right answer too...But it doesn't. Instead to really throw you off, the answer is 2.000000000000004. I don't do too much Mathematical programming that involves irrational numbers, but if I was someone who did, a whole afternoon would've probably been wasted tracking this down. Either way it was cool to see JavaScript mess up. Turns out all this is caused by IEEE-754.

It probably doesn't stop there either, but I will, because I have more reading to do. Again I extremely recommend this book to anyone who wants to start doing Math again. It has been a blast.

Comments

  1. http://0.30000000000000004.com/

    ReplyDelete
    Replies
    1. > Your language isn't broken, it's doing floating point math.

      Perfectly said.

      Delete
  2. Though not exactly related, well, it's not related at all, but I felt this was an appropriate thing to link you to: https://mathwithbaddrawings.com/2016/03/23/decimal-crazed-lunatics/

    1/3 is not 0.33333... repeating. Because at some point, you'll have to stop.

    ReplyDelete

Post a Comment

Popular Posts