Course: JavaScript

Progress (0%)

JavaScript Numbers Basics

Chapter 15 48 mins

Learning outcomes:

  1. Integers and floats
  2. Number primitives and Number objects
  3. Flooring and ceiling
  4. Scientific notation and the symbol e
  5. Converting to a number
  6. Special numbers — NaN and Infinity
  7. Checking for special numbers — isNaN() and isFinite()

Introduction

No one can ignore the significance of numbers in programming. They are used in numerous applications out there which could span a whole book if one just starts to name them. Quantum computing, basic computing, the internals of computers — everything relies on numbers.

In this unit, we build our foundation on JavaScript numbers. We'll see the different types of numbers in programming, and JavaScript's convention to consider every number under one type; how to process numbers; how to round them, perform mathematical operations on them and much more; special cases of numbers such as NaN and Infinity; and so on.

Let's begin.

Integers and floats

Numbers are generally divided into 2 categories: integers and floats.

Let's start with the first category.

Integers are whole numbers, without a decimal point in them.

Examples include 0, 1, 2, 3 etc. Integers can also be negative, such as -1, -2, -3 etc.

In JavaScript, an integer can be denoted just as we denote it in normal writing. Consider the code below:

var num = 10;

Here we create a variable num and assign an integer value 10 to it.

Now let's see the other category — floats

Floating-point numbers, or simply floats, are numbers with a decimal point in them.

Examples include 1.5, 2.3, 7.2. As with integers, floats can also go into the negative range, for instance -1.5, -50.123, -1000.009 etc.

Creating a floating-point number in JavaScript is also pretty basic, just write the number as it is.

Consider the code below:

var num = 10.5;

Here we create a variable num and assign a float value 10.5 to it.

Simple!

Now before we move on, it's extremely important to clarify one thing.

JavaScript treats all numbers, whether they are integers or floats, under one single type and that is number. In other words, -1, -1.5, -2, -0.005, 0, 1000, 105.855 are all just numbers in JavaScript.

Even internally, all numbers are stored in the same way in JavaScript. That is using the IEEE-754 double precision floating-point format.

Typically, integers in other programming languages are stored using the 2's complement format while floating-point numbers are represented differently, using the IEEE-754 format.

In other words, all numbers in JavaScript are stored internally in the format of a floating-point number. As we shall see later on, this could result in some unexpected consequences when doing integer arithmetic.

Now, the next time you see an integer in JavaScript, such as 10, you'll know that internally it's not represented as an integer, but rather as a floating-point number.

Number primitives and objects

Back in the JavaScript Data Types chapter, we saw what are primitives and objects in the language. Let's get a quick review over number primitives before considering the equivalent object type.

A primitive is a value with no properties/methods attached to it.

In JavaScript, there are 5 main primitive types: numbers, strings, Booleans, undefined, and null (additional two being symbols and big integers, but we won't be considering them in this course).

For now, we are concerned with the first of these types, i.e. numbers.

A number primitive is created using number literals.

Recall that a literal is an exact representation of a value in the source code. In JavaScript, numbers can only be denoted literally.

Examples of number literals are 0, 1, 2, 0.5, 0.00123 and so on and so forth.

Number literals create number primitives, i.e numeric values that don't have any properties/methods attached to them.

Consider the following code:

var x = 50.5;

Here we create a variable x and then assign a numeric literal 50.5 to it. This literal creates a number primitive. So x holds a number primitive; it has no properties/methods attached to it.

In the snippet below, we perform a couple of arithmetic operations using numeric literals:

10 + 10
20
50 + 0.5
50.5
20.5 + 0.5
21
10 - 5
5

To check whether a given primitive value is a number, we could use the typeof operator.

Recall its return value on numbers?

typeof returns 'number' when used to inspect a number primitive.

An example follows:

typeof 10
'number'
typeof 0.005
'number'
typeof -3
'number'

Although they're used almost never, in JavaScript, in addition to number primitives, we could also create number objects.

To create a number object, we use the Number() function and call it using the new keyword. When called with new, a function is referred to as a constructor.

We'll explore all details regarding constructors in the chapter JavaScript Objects — Constructors.

Shown below is the syntax of Number() called as a constructor:

new Number([value]);

value specifies the value to represent as a numeric object. If omitted, it defaults to 0. (Recall that square brackets around an argument in a syntax snippet represent an optional argument.)

Let's create a couple of number objects.

When given no argument, new Number() creates a Number object whose equivalent primitive value is 0. This can be seen in the following code:

var num = new Number();
console.log(num);
Number {0}

Let's see what does typeof return when used to inspect a number object:

var num = new Number();
console.log(typeof num);
object

As can be seen, typeof returns 'object' for a number object. In contrast to this, as we remember from the discussion above, it returns 'number' for a number primitive.

To create an object for some other number, we pass the number as an argument to the Number() constructor.

Shown below is an example:

var num = new Number(10);
console.log(num);
Number {10}

Here, we create a number object num over the primitive 10.

Number objects are numbers as well and so could be used in arithmetic operations too. The return value of these operations is, however, a number primitive, NOT an object.

Shown below is a snippet where we perform arithmetic operations over number objects:

new Number(10) + new Number(20)
30
new Number(10) - new Number(20)
-10
new Number(10) * new Number(20)
200
new Number(10) / new Number(2.5)
4

Now as you can clearly see in both the code snippets above, creating a number object over a given number other than 0 requires us to use a number literal anyways.

In other words, there is absolutely no point of using new Number() to create a number in a JavaScript program.

new Number() is something that the JavaScript engine is configured to automatically run behind the scenes when it feels the need to.

Let's understand this phenomenon in detail...

The purpose of the Number() constructor

As we shall see in the next chapter on JavaScript Number Methods, there are a couple of methods that can be called on a given number in JavaScript. For instance, let's consider the method toString().

When called on a number, toString() coverts it into an equivalent string representation. Note that the actual number isn't changed — a copy of the number is made and then that copied number is converted into a string.

Shown below is how we would typically call toString():

var num = 10;
undefined
num.toString()
'10'

Now you might be stunned by looking at this code. Why do we say so?

Because we are accessing a method on num, which is a primitive; and we know that primitives do NOT have properties/methods attached to them.

Accessing a property/method on a primitive conflicts with what we've been learning so far uptil now that primitives don't have methods available on them.

So does this mean that what we stated earlier in this course regarding primitives was wrong?

Well no! What we learnt was perfectly valid. And it holds in the code above as well — the number primitive num really doesn't have any properties and methods on it!

The code above just looks as if it accesses a method on the primitive num, but behind the scenes, it's a different story. Let's dive deeper...

The moment the JavaScript interpreter sees that a property/method is being accessed on a primitive, it boxes that primitive into an object and performs the property access on that object.

Each of the three primitive types — numbers, strings and Booleans, have a corresponding function that could be called in the context of a constructor to create an object for that primitive type.

For numbers, as we just saw a few momemnts ago, that function is Number(). When called in the context of a constructor, i.e. using the new keyword, it returns an object of type Number.

The code above is automatically translated to something as follows:

var num = 10;
var _num = new Number(num); // Done automatically by JavaScript
console.log(_num.toString());
_num = null;

Notice the imaginary identifier _num in here. Each access of the primitive value num is replaced by this value _num. In this way, it just seems as if toString() is being accessed directly on the primitive num but that's not the case — it's rather accessed on the wrapper number object _num.

In the end, this wrapper object is deleted from memory by setting _num to null.

The code shown above is just to give you an idea of what happens internally in the JavaScript engine when a property is accessed over a primitive value. It is NOT the exact depiction of the internals of JavaScript which might have numerous tedious details to coping with such statements!

So to boil it down, this is the only use of new Number(), and the rest of the wrapper types as well — to box primitives when they are used as objects.

They are really never required explicitly in a program.

It's recommended to always stick to using primitive values since they make coding easy, and reduce unnecessary clutter on the memory.

Before we end this section, it's extremely important to note that the Number function itself is quite useful, as we shall see later on in this chapter. It's only its usage in the form of a constructor that is redundant.

Flooring and ceiling

In mathematics, there are two highly useful functions (not the functions we use in JavaScript) that are used to round given numbers to integers.

They are the floor and ceil functions.

The floor function is denoted as ::f(x) = \lfloor x \rfloor::. Given a number ::x::, it returns back the largest integer less than or equal to ::x::. For instance, ::\lfloor 10.999 \rfloor:: gives us ::10::.

On the other hand, the ceil function is denoted as ::f(x) = \lceil x \rceil::. Given a number ::x::, it returns back the smallest integer greater than or equal to ::x::. For instance, ::\lceil 10.001 \rceil:: gives us ::11::.

In JavaScript, these functions are available as methods on the global Math object as floor() and ceil(), respectively.

Math.floor(x) takes an argument x and returns its floor, while Math.ceil(x) takes an argument x and returns back its ceiling.

Shown below are a handful of examples.

First for Math.floor():

Math.floor(10.5)
10
Math.floor(10)
10
Math.floor(10.99999)
10
Math.floor(-5.6)
-6
Math.floor(-5.1)
-6
Math.floor(-5)
-5

Now for Math.ceil():

Math.ceil(10.5)
11
Math.ceil(10)
10
Math.ceil(10.0005)
11
Math.ceil(-5.6)
-5
Math.ceil(-5.1)
-5
Math.ceil(-5)
-5

As you can see in these snippet, calling Math.floor() or Math.ceil() on an integer returns back the integer, as it is.

In JavaScript, as you implement numerous commonly-used algorithms, you'll find yourself using the Math.floor() and Math.ceil() methods quite frequently.

Scientific notation

When representing huge or minute numbers with a large number of digits in them, it's convenient to reduce them down to scientific notation.

Scientific notation, also known as standard form, standard notation, and E notation (on digital devices), is when a number is represented in the form shown below,

::m \times 10^n::

where ::m:: is the mantissa, ::10:: is the base, and ::n:: is the exponent. (We'll see how to use this shortly below.)

Scientific notation is used quite frequently in mathematics, and scientific calculations, to represent extremely small or extremely large numbers.

For instance, the number ::0.000000000000003756:: could be represented as ::3.756 \times 10^{-15}::, where ::3.756:: is the mantissa and ::-15:: is the exponent. Similarly, the number ::20210000000000000000000000:: could be represented compactly as ::2.021 \times 10^{25}::.

In both these examples, see how the numbers expressed in scientific notation are way easier to read and write, as compared to their counterparts in normal decimal notation.

Coming back to JavaScript, the symbol e is used to represent numbers in scientific notation.

The syntax is detailed below:

<mantissa>e<exponent>

The number begins with the mantissa, followed by the symbol e, followed by the exponent. Note that the exponent must be an integer.

Shown below are a handful of examples:

1e3
1000
3.254e2
325.4
100e2
10000

As in mathematics, scientific notation in JavaScript could contain negative exponents (but they must be integers as well):

1e-3
0.001
123e-1
12.3
100e-2
1

Keep in mind that JavaScript numbers are based on the IEEE-754 format, and so the maximum number possible to be represented in the language is roughly less than 1.8e308.

Creating a number larger in value than this maximum limit (or even equal to it) would result in it being replaced with the special value Infinity (more on this below) as shown below:

5e1000
Infinity
1e310
Infinity
1e100 * 2e250
Infinity
1.8e308
Infinity

In fact, this maximum value can be precisely accessed via the Number.MAX_VALUE property.

Details follow in the snippet below:

The Number.MAX_VALUE property

The MAX_VALUE property on the Number object represents the maximum number storable in JavaScript, based on the IEEE-754 floating-point format.

Number.MAX_VALUE
1.7976931348623157e+308

Going beyond this value would result in Infinity:

Number.MAX_VALUE * 2
Infinity

Surprisingly though, adding a small number to MAX_VALUE would return back the same number, not the expected value Infinity:

Number.MAX_VALUE + 1
1.7976931348623157e+308

This isn't a bug per se; it just has to do with how floating-point numbers are stored internally (and that's quite a complex format).

Converting to a number

There are multiple applications of converting from a given value into a number.

For instance, after obtaining input from the user (for e.g. via prompt()) we may want to perform some arithmetic operation on it. This requires the input, which is always a string, to be first converted into a number and then the operation performed on the number.

JavaScript provides developers with quite a decent amount of ways to convert a given value into a number. Below, we go over each of these ways one-by-one.

Number()

The first choice is to use Number().

We are aware of this function being used for converting a given value into a number back from the JavaScript Basics chapter.

Before we begin, take note of one thing that the Number() function is different from the Number() constructor.

Yes, they both utilise the same function but the former calls the function in the context of a function and returns back a number primitive, whereas the latter calls the function in the context of a constructor and returns back a number object.

In the discussion above, we said that it's recommended to avoid the Number() constructor which creates number objects; not to avoid the Number() function (without the new keyword) which allows us to convert given values into an equivalent numeric representation.

The Number() function takes in an argument and returns back a number equivalent of the given value.

Number([value])

Usually the argument is a string, but could be any value in JavaScript.

Shown below is the conversion table:

ValueNumeric equivalent
NumberThe number itself
'' (empty string)0
Non-empty stringParsed
true1
false0
undefinedNaN
null0
ObjectParsed

Let's see a couple of examples of working with Number():

Number('50')
50
Number('3.142')
3.142
Number(true)
1
Number(false)
0

In the first statement, we pass '50' to Number() and likewise gets 50 returned back. In the second statement, we pass another such string, this time holding a float, i.e. '3.142', and likewise get 3.142 returned.

In the next two statements, we pass the Booleans true and false to the function and get the equivalent values returned — 1 for true and 0 for false.

When the argument to Number() is the value undefined or a string that contains a non-numeric character, the function returns NaN.

NaN is a special number in JavaScript. It stands for 'Not a Number', and is used to represent the result of expressions or invocations that don't give a meaningful number.

Consider the snippet below:

Number('20a')
NaN
Number('a20')
NaN
Number('abc')
NaN

The string '20a' contains a non-numeric character at the end, and so the JavaScript interpreter couldn't understand how to convert it into an equivalent number. It simplifies its work by returning NaN for such a string that couldn't be parsed fully into a number.

At this point, it's the high time for you to go to the console and start experimenting by converting different values to numbers using Number().

parseInt()

Sometimes, as we've seen above, Number() can't correctly parse a number out of a string. For instance, consider the string '42px'. Number('42px') returns NaN because the string contains non-numeric characters.

This kind of a conversion can be often needed when retrieving the value of a CSS property in JavaScript (we'll see how to do so in the JavaScript HTML DOM unit).

Unfortunately, as we've seen, Number() can't be used in such a case. Now what?

Well, we could use the parseInt() function to solve such a conversion problem.

Let's see its syntax:

parseInt(string[, radix])

string specifies the value to parse into a number — or better to say, into an integer. The radix argument is not important for now. We'll consider it later on in this chapter.

Internally, in parseInt(), string is coerced into a string, so if you specify a non-string value as string, it would be converted into a string and then parsed into an integer.

The way parseInt() parses string (after being coerced into a string) is demonstrated as follows:

  1. Whitespace is trimmed from the start of the string.
  2. If the first character of the resulting string is -, it's removed from the string and the fact is remembered that the final parsed number has to be negatively signed.
  3. The index of the first non-integer digit (which includes the minus sign (-), the space character and all alphabetic characters in addition to many other string characters) in the resulting string is noted down.
  4. If this index is 0, NaN is returned.
  5. A slice is extracted from the string, starting at the index 0 and ending at the index obtained in step 3 (this index is exclusive).
  6. This slice is converted into an integer.
  7. The integer is made negatively signed if the condition in step 2 was met.
  8. The resulting integer is finally returned.

In short, parseInt() parses an integer out from the starting portion of a string.

Consider the snippet below:

parseInt('50')
50
parseInt('10px')
10
parseInt('a50')
NaN
parseInt('-50')
-50
parseInt('--50')
NaN
parseInt('    20')
20
parseInt('50.5')
50

The last statement here is quite interesting. What is given is a stringified number, specifically a stringified float '50.5', yet parseInt() returns back an integer leaving off the fractional part. Well this is just what the function is meant to do — parse and return an integer out of a given string; not to parse and extract out a float.

To parse a float out of a given string, we need to use the parseFloat() function, specifically made for such cases.

parseFloat()

The parseFloat() function behaves similar to parseInt() except for that it parses floats out of the given argument.

Here's its syntax:

parseFloat(string)

string is the value to convert into a float — or better to say, into a number (as integers and floats are represented the same way in the format of floats).

If you recall one thing, all numbers in JavaScript are internally stored as floats. This means that parseFloat() could even extract out an integer from a given string. The reason is because even integers are floats in JavaScript, so technically parseFloat() would be extracting out a float in this case as well.

Anyways, shown below are some examples of using parseFloat():

parseFloat('20.5a')
20.5
parseFloat('20a')
20
parseFloat('-100.123abc')
-100.123
parseFloat('a20')
NaN
parseFloat('abc')
NaN

Take note of the last two cases here — the string has a non-numeric character at the beginning, and therefore gets the function's call to evaluate down to NaN.

Moving on, at this point, you might have one question in your mind: shall I use parseInt() or parseFloat()?

Well, let's make a simple rule...

parseInt() or parseFloat()?

If you know that a string you wish to convert to a number has non-numeric characters at the end, you know that you couldn't use Number(), and just have to choose between parseInt() and parseFloat().

Now if you are not sure on exactly what type of number would be there in the beginning, it's better to use parseFloat() since it could extract out both integers and floats from a string.

However, if you do know that the string would always have an integer in the beginning, it's better to use parseInt() as it does less of the parsing than parseFloat().

Unary plus (+) operator

Apart from the three functions shown above, there is yet an even simpler way to convert a given value into a number.

That is using the unary plus (+) operator.

The unary plus (+) operator takes an expression, converts it into a number and returns back the number.

Here's its syntax:

+expression

The unary plus operator is basically a shorthand notation for calling Number() on a given value. The rules for conversion are exactly the same as for Number().

Let's see it in action:

+'20'
20
+'10.123'
10.123
+'-5.1'
-5
+'NaN'
NaN
+'Infinity'
Infinity
+'20a'
NaN
+true
1

If you want to convert a given value into a number using the Number() function, you could instead use this simpler operator syntax to do that.

The best thing about unary plus is that it has an amazing browser support — it's fully supported even on IE6!

You can check out more details at CanIUse.com - browser support for unary plus.

Special numbers

Following from the fact that numbers in JavaScript are based on the IEEE-754 format, there are two special cases of numbers in the language.

One is NaN and the other one is Infinity.

Both of these values are identifiers in JavaScript, not keywords. Assigning a value to NaN or Infinity won't throw an error (in non-strict mode) but would rather go ignored, since these identifiers are read-only.

Since NaN and Infinity are identifiers, they are case-sensitive.
In strict mode, assigning a value to NaN or Infinity throws an error.

Let's understand what do both these special numbers mean...

NaN

Starting with NaN:

NaN stands for 'Not a Number' and is used to represent the result of a numeric expression that couldn't be a number or one that couldn't be defined.

An example is Number('a') — an alphabetic character can't convert to a number but because Number() has to return back a number, what it does is that it returns the special number NaN.

Consider the snippet below where we show a couple of expressions that evaluate down to NaN:

Number('a')
NaN
+'20a'
NaN
Infinity - Infinity
NaN
0 / 0
NaN

Infinity

Now, let's consider Infinity:

Infinity is used to represent the result of a mathematically impossible calculation or an expression that exceeds in value beyond Number.MAX_VALUE.

Some examples are 1 / 0 and 2 ** 2 ** 20 (this is a humongous number with over 300000 digits!)

Similarly, below we demonstrate a couple of expressions that evaluate down to Infinity.

1 / 0
Infinity
20 ** 1000
Infinity

Checking for special numbers

If we want to check whether a given number is NaN or Infinity, we can use two dedicated functions to accomplish this.

They are isNaN() and isFinite(), respectively.

isNaN()

The isNaN() function simply tell us whether a given value is NaN or not.

Let's see its syntax:

isNaN(value)

value is a number or some other value, in which case it's first coerced into a number before proceeding forward.

If value is NaN, the function returns true, or false otherwise.

The snippet below illustrates the function as called on a couple of values:

isNaN(2)
false
isNaN(Infinity)
false
isNaN(NaN)
true
isNaN(Infinity - Infinity)
true
isNaN('abc')
true

Recall that Infinity - Infinity returns NaN, likewise isNaN() returns true in the second last statement here.

For the last statement, since the value 'abc' is not a number, it's first converted into one. This conversion follows the same rules as Number(). Since Number('abc') returns NaN, the last statement above becomes isNaN(NaN) which obviously returns true.

Why we need isNaN()?

As a beginner JavaScript developer, you might be intrigued to think that you won't need isNaN() to check whether a given number is NaN, and that the following check would do it all:

var num = NaN;
console.log(num === NaN); // false

Extremely surprisingly, the last statement here logs false, even though both the values being compared are equal to NaN.

Why? Why does NaN === NaN return false?

This is part of the IEEE-754 spec which states that two 'nan' values aren't equal to one another.

isFinite()

The isFinite() function tells us whether a given value is finite or not.

Syntactically, it's similar to isNaN():

isFinite(value)

value is a number, or coerced into one if it's not a number. The return value of the function is true if value is finite i.e. not Infinity, NaN and undefined; or otherwise false.

The code below illustrates isFinite() on a couple of numbers:

isFinite(2 ** 10000)
false
isFinite(2)
true
isFinite('10')
true
isFinite(Infinity)
false
isFinite(NaN)
false
isFinite(undefined)
false

Infinity could be compared manually

Unlike NaN, the special number Infinity could be compared manually to a given value to determine whether that value is equal to Infinity or not.

An example follows:

var num = Infinity;
console.log(num === Infinity); // true

"I created Codeguage to save you from falling into the same learning conundrums that I fell into."

— Bilal Adnan, Founder of Codeguage