Categories
JavaScript Best Practices

Better JavaScript — Floating-Point and Coercions

Spread the love

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at ways to improve our JavaScript code.

Floating Point Numbers

Floating-point numbers are tricky in JavaScrtipt because of rounding.

For instance, if we have:

0.1 + 0.2;

Then we get:

0.30000000000000004

Double-precision floating-point numbers can only represent a finite set of numbers, rather than an infinite set of real numbers.

This means that floating-point arithmetic can only produce finite results.

The rounding errors can accumulate when we round in one or more operations.

This makes the result less and less accurate.

Math operations like addition is associative, so (x + y) + z = x + (y + z).

But this isn’t the case with floating-point arithmetic.

So if we have:

(0.1 + 0.2) + 0.3; 

We get:

0.6000000000000001

But:

0.1 + (0.2 + 0.3);

returns 0.6.

With integers, we’ve to make sure that the range of each result is between -2 ** 53 and 2 ** 53 .

Implicit Coercions

We got to be aware of implicit coercions.

They’re going to be a problem for us when we write JavaScript.

For instance, we can write:

2 + true;

and get 3.

true is converted to 1 so we get 3.

There’re some cases that JavaScript gives us the error if we use the wrong type.

For instance, if we have:

"foo"(1);

We get ‘Uncaught TypeError: “foo” is not a function’.

And undefined.x gets us ‘Uncaught TypeError: Cannot read property ‘x’ of undefined’.

In many other cases, JavaScript coerces the value to what it thinks it should be.

So if we write:

2 + 1;

then JavaScritp assumes that we’re adding 2 numbers.

And if we write:

"foo" + " bar";

Then we’re concatenating 2 strings.

If we combine a number and a string, then it’s more confusing.

If we have:

1 + 2 + "3";

or

(1 + 2) + "3";

then we get '33' .

But if we have:

1 + "2" + 3;

We get “123” .

It just converts to the type according to its own rules, so it’s not very predictable.

Type coercion hides errors, so we only know that we have a bug if the code doesn’t do what we expect.

Rather than throwing an exception, we just see results we don’t expect.

Also, NaN is considered to be not equal to itself, which is more confusing.

We’ve to call isNaN to check for NaN .

So:

isNaN(NaN); 

returns true .

But:

let x = NaN;   
x === NaN;

returns false .

Silent coercions make debugging harder since it covers up errors and makes them harder to find.

When calculation goes wrong, we’ve to inspect each variable to check where something goes wrong.

Objects can also be coerced to primitives.

So if we have:

'' + Math

we get “[object Math]” .

And:

'' + JSON

returns “[object JSON]” .

Conclusion

Floating-point arithmetic and data type coercions are both tricky with JavaScript.

We got to make sure we coerce data types as little as possible to reduce the chance of frustrating bugs.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *