const - JS | lectureNumbers, Dates, Intl & Timers

Converting and Checking Numbers

Numbers, Dates, Intl & Timers

The first thing you should know about numbers is that all numbers are represented internally as floating point numbers in JavaScript. So basically, they are always decimals, whether we write them as integers or decimals.

We can check that by doing the following:

script.js
console.log(17 === 17.0); // true

You can see that the result is true. And that's the reason why we only have one data type for all numbers.

Also, numbers are represented internally in a 64-base 2 format. So that means that numbers are always stored in a binary format. i.e., composed of 0s and 1s.

Now, in binary form, it is very hard to represent some fractions that are very easy to represent in the base 10 system we are used to.

Let' have an example:

script.js
console.log(0.1 + 0.2); // 0.30000000000000004

This is kind of a classic or running joke in JavaScript because the result should, of course, be 0.3 and not what we had above. But JavaScript simply has no better way of representing this number. So in base 10, 1/10 is simply 0.1. And so that's very easy to represent. But, for example, if we were trying to do 10/3, that is also impossible for us to represent because we will have an infinite number of 3 after the decimal.

Now, in some cases, JavaScript does some rounding behind the scenes to try its best to hide these problems, but some operations, such as the one above, cannot mask the fact that behind the scenes, they cannot represent certain fractions.

And by the way, many other languages use the same system. For example, PHP or Ruby, so don't let anyone make fun of JavaScript 😅. So we just have to accept that it works this way because we cannot do anything against it. Also, be aware that you cannot do like really precise scientific or financial calculations in JavaScript because eventually, you will run into a problem like this:

script.js
console.log(0.1 + 0.2 === 0.3); // false

This should be true but well, this is simply an error in JavaScript that we have to accept.

Now that we know how JavaScript represents numbers, let's start working with them. To convert a string to a number, we usually do the following:

script.js
console.log(Number('17')); // 17

But there is also an easier way. Some kind of trick that we can use. Which is to add a plus sign in front of the string:

script.js
console.log(+'17'); // 17

This works because, when JavaScript sees the plus operator, it will do type coercion. That is, it will automatically convert all the operands to numbers.

We can also do something called parsing. That is, we can parse a number from a string using the parseInt method that is available on the Number object. Remember that every function is also an object. Let's have an example:

script.js
console.log(Number.parseInt('17rem')); // 17

In order to make this work, the string has to start with a number. So, for example, the below will not work:

script.js
console.log(Number.parseInt('px17rem')); // NaN

This is a little bit like type coercion but even more advanced because as we just saw, it tries to get rid of unnecessary symbols that are not numbers.

The parseInt method accepts a second argument, which is the so-called radix. The radix is the base of the numeral system that we are using. In the example above, we are using the base 10 system. But we can also use the base 2 system, for example, if we want to convert a binary number to a decimal number:

script.js
/**
 * If the radix is 0 or undefined, the radix is assumed to be 10
 * except when the number begins with the "0x" or "0X" prefix, in which case the radix is 16.
 */

// Base 10
console.log(Number.parseInt('17px', 10)); // 17

// Base 2
console.log(Number.parseInt('111', 2)); // 7

Next, we also have the parseFloat method. This is very similar to the parseInt method, but it will only parse floating point numbers. So it will not parse integers. Let's have an example:

script.js
console.log(Number.parseFloat('17.5rem')); // 17.5
console.log(Number.parseInt('17.5rem')); // 17

Both parseInt and parseFloat are so-called global functions. So we would not need to use the Number object to call them. We could simply do the following:

script.js
console.log(parseInt('17.5rem')); // 17
console.log(parseFloat('17.5rem')); // 17.5

But this is the traditional and old way of doing it. In modern JavaScript, it is more encouraged to call these functions on the Number object. So we say that Number provides a namespace for these functions.

Let's now explore another function of the Number namespace, which is the isNaN function. This function is used to check if a value is NaN. Let's have some examples:

script.js
// Use this to check id value is NaN
console.log(Number.isNaN(20)); // false
console.log(Number.isNaN('20')); // false
console.log(Number.isNaN(+'20X')); // true

Let's try something else:

script.js
console.log(23 / 0); // Infinity
console.log(Number.isNaN(20 / 0)); // false

I guess you already know that dividing by 0 gives us Infinity. Hence, Infinity is not a NaN value. So Number.isNaN will return false in this case.

The Number.isNaN function is actually not a perfect way for checking if a value is a number because it doen't consider the above use case and sometimes, it can very well happen. Hence, there is a better method called Number.isFinite.

Let's have the same examples as above but using Number.isFinite:

script.js
// Best way to check if a value is a number
console.log(Number.isFinite(20)); // true
console.log(Number.isFinite('20')); // false
console.log(Number.isFinite(+'20X')); // false
console.log(Number.isFinite(20 / 0)); // false

This method is the ultimate method that you should use to check if any value is a number, at least when you're working with floating point numbers. So if you are sure that you just need to check for an integer, then you can use isInteger as well.

script.js
console.log(Number.isInteger(23)); // true
console.log(Number.isInteger(23.0)); // true
console.log(Number.isInteger(23 / 0)); // false