Course: JavaScript

Progress (0%)

  1. Foundation

  2. Numbers

  3. Strings

  4. Conditions

  5. Loops

  6. Arrays

  7. Functions

  8. Objects

  9. Exceptions

  10. HTML DOM

  11. CSSOM

  12. Events

  13. Drag and Drop

  14. opt Touch Events

  15. Misc

  16. Project: Analog Clock

JavaScript Number Methods

Chapter 16 20 mins

Learning outcomes:

  1. Rounding to given significant figures using toPrecision()
  2. Rounding to given decimal places using toFixed()
  3. Converting to scientific notation using toExponential()
  4. Converting numbers to binary, octal and hexadecimal

Introduction

All programming languages appreciate the significance of numbers in computing and likewise provide utilities to easily work with them. JavaScript is no way behind — the language comes packed with a ton of things to facilitate in working with numbers.

In this chapter, we'll explore some methods natively available to JavaScript numbers via the Number interface, which we discovered in the previous chapter, JavaScript Numbers — Basics.

Specifically, we'll go over the different ways to round numbers in JavaScript and then consider conversions to different numerical bases including binary, octal, and hexadecimal.

Rounding to significant figures

The toPrecision() method of the Number interface rounds a number to a given significant figure precision.

Its syntax is pretty basic:

number.toPrecision(precision)

The precision argument specifies the number of significant figures to round the given number number to. The method then returns back a string holding number in its rounded form.

Note that precision must be between 1 and 100. Giving a value out of this range would result in an error.

If precision is a non-numeric value, or a value with a non-zero fractional part, it is converted to the nearest integer. This makes sense because the argument can only be an integer — we can't have 0.5 significant figures in a number!

Shown below are a bunch of examples.

First, let's see how are integers rounded:

58 .toPrecision(2)
'58'
58 .toPrecision(3)
'58.0'
124 .toPrecision(3)
'124'
124 .toPrecision(4)
'124.0'

(Take note of the space after every number written above and the toPrecision() method. This is necessary, as detailed in the snippet below.)

In the first statement, calling toPrecision() on 58 has no effect since the number already has 2 significant figures. In the second statement, the function returns a string containing a number with 0 added after the decimal point, i.e. 58.0, to act as the third significant digit.

A similar reasoning applies to 124.

Why is there a space in 58 .toPrecision(2)?

Notice the space between each number and .toPrecision() in the code above:

  • 58 .toPrecision(2)
  • 58 .toPrecision(3)
  • 124 .toPrecision(3)
  • 124 .toPrecision(4)

It is necessary. Why?

This ensures that the JavaScript interpreter doesn't parse the . as a decimal point.

Removing the space, such as in 58.toPrecision(), would lead to a syntax error.

console.log(58.toPrecision(2)); // No space before .toPrecision()
Uncaught SyntaxError: Invalid or unexpected token

This is because with the space removed, the parser thinks that the . is a decimal point, specifying the previous number's fractional part, and so would be followed by numeric digits.

But since this doesn't happen, and the . is instead followed by the word toPrecision, the parser raises a syntax error.

Time for a very quick quiz:

What would 10 .toPrecision(4) return?

  • 10
  • '10'
  • 10.00
  • '10.00'

Now let's work with a couple of floats:

1.2386 .toPrecision(2)
'1.2'
1.2386 .toPrecision(3)
'1.24'
1.2386 .toPrecision(4)
'1.239'

In the first statement, the number 1.2386 is rounded to 2 significant figures, i.e. to the first decimal place. This causes the number to be rounded down to 1.2, and then obviously coerced into a string.

In the second statement, the same number is rounded to 3 significant figures, i.e. to the second decimal place. This rounds the number to 1.24, then returning '1.24'.

A similar explanation applies to the last statement as well.

Moving on, in cases where precision is less than the number of digits already in the given number, the returned string is in scientific notation.

Consider the snippet below:

58 .toPrecision(1)
'6e+1'
124 .toPrecision(1)
'1e+2'
124 .toPrecision(2)
'1.2e+2'
178 .toPrecision(2)
'1.8e+2'
17000 .toPrecision(1)
'2e+4'
17000 .toPrecision(2)
'1.7e+4'
17000 .toPrecision(3)
'1.70e+4'
17000 .toPrecision(4)
'1.700e+4'
17000 .toPrecision(5)
'17000'

In the first statement, the number 58 has two digits in it while the argument to toPrecision() is 1. Clearly, this argument is less than 2, hence the representation returned by toPrecision() is in scientific notation. 58 rounded to 1 s.f. (significant figure) is 60, which is equivalent to 6e+1.

A similar explanation applies to the rest of the given statements.

In the last statement, the number of digits in 17000 and the argument to the toPrecision() method are both equal to one another, i.e. 5, so there is no conversion to scientific notation in the returned stringified number.

Stating it again, scientific notation is only used when the precision argument to toPrecision() is less than the number of digits displayed for the given number.

Now as you might agree, in cases where the resulting number (after this rounding) could otherwise be easily represented in normal decimal notation, this conversion to scientific notation could seem way too much.

Is there any way to solve it?

Hmm. Well, there is NO way to do so natively in JavaScript. But we could create our own function to solve this problem.

In the upcoming exercise, JavaScript Numbers — Better Precision, we'll get you to create such a function, processing the return value of toPrecision().

Anyways, moving on, sometimes instead of wanting to round a number to given significant figures, it's desired to round it to given decimal places. This can be accomplished using the toFixed() method.

Rounding to decimal places

The toFixed() method rounds a number to a given number of decimal places. And it also returns back the result in the format of a string (akin to toPrecision()).

The toFixed() method is commonly used in applications dealing with billing, currency, and financial statistics. Currency is typically represented with precision of 2 decimal places, i.e $0.00, $2.25, $100.07, etc.

Following is the syntax of toFixed():

number.toFixed([digits])

digits is the number of digits to place after the decimal point in the returned stringified number. By default, digits is set to 0.

Remember that [] in the syntax snippet above doesn't represent an array but rather an optional parameter of a function.

Here's a demonstration of toFixed() on a couple of numbers:

1 .toFixed()
'1'
1 .toFixed(0)
'1'
1 .toFixed(1)
'1.0'
1 .toFixed(2)
'1.00'
1 .toFixed(5)
'1.00000'
1.1286.toFixed()
'1'
1.1286.toFixed(0)
'1'
1.1286.toFixed(1)
'1.1'
1.1286.toFixed(2)
'1.13'
1.1286.toFixed(3)
'1.129'

Time for a quick quiz again:

What would -7.14165 .toFixed(3) return?

  • -7.141
  • '-7.141'
  • -7.142
  • '-7.142'

Let's now consider a practical example using toFixed().

In the code below, we log our total bill in an imaginative shopping app, by multiplying the price of an item (price) with its total quantity (qty):

var price = 3; // Price in $
var qty = 10;

console.log('Your total bill is: $' + (price * qty).toFixed(2));
Your total bill is: $30.00

Simple isn't it.

If you're thinking as to why is this method called 'toFixed', curious about the meaning of 'fixed' in there, the next snippet is for you.

Why is toFixed() called 'toFixed'?

The naming of an identifier shall always be the first step in understanding what it's meant for. Let's see where does the name 'toFixed' come from.

In programming, as we already know by now, we have floating-point numbers, where the decimal point literally 'floats' — it's not fixed at a given position. Unlike this, in fixed-point numbers, the decimal point is 'fixed', and always followed by the same number of digits.

Coming back to toFixed(), it converts a given number into a notation resembling that of a fixed-point number and that's exactly why we call it 'toFixed'.

Simple.

Converting to scientific notation

To convert any number into scientific notation, we use the toExponential() method.

The toExponential() method takes in an argument and returns back a string holding its equivalent value in scientific notation.

Here's the syntax:

number.toExponential([fractionDigits])

fractionDigits gives the number of digits to put after the decimal point in the final scientific notation. If omitted, the number is converted to the most appropriate scientific notation.

Let's see some quick examples:

152 .toExponential(0)
'2e+2'
152 .toExponential(1)
'1.5e+2'
152 .toExponential(2)
'1.52e+2'
152 .toExponential()
'1.52e+2'

Shown below are even more examples, this time using actual floating-point numbers:

243.74.toExponential(0)
'2e+2'
243.74.toExponential(1)
'2.4e+2'
243.74.toExponential(2)
'2.44e+2'
243.74.toExponential(3)
'2.437e+2'

If you carefully notice, when the argument to toFixed() is less than the number of digits in the underlying number, its return value is the same as calling toExponential() with the same argument.

In other words, toFixed() internally either does some processing of its own or just calls toExponential().

Converting numbers to different bases

A highly useful method of numbers in JavaScript, but one that perhaps isn't cheered that much, is the toString() method.

Although toString() merely converts a number into a string when called with no arguments, if it is provided with an argument, it converts the number into the given base n representation.

number.toString([radix])

If provided, the argument has to be a number, specifying the radix of the converted number.

A number's radix, more commonly known as its base, specifies the numeric system on which the number is based.

Some common bases are base 2, known as binary; base 8, known as octal; and base 16, known as hexadecimal. The number system we use has the base 10, and commonly referred to as the decimal number system.

To illustrate this, following we convert the decimal number 15 into each of the following three representations: binary, octal, and hexadecimal:

var num = 15;

// Conversion to binary
var binNum = num.toString(2); // '1111'

// Conversion to octal
var octNum = num.toString(8); // '17'

// Conversion to hexadecimal
var hexNum = num.toString(16); // 'f'
In hexadecimal, f stands for the number 15.
Since we can't have the bases 0 or 1 to represent numbers, calling toString(0) or toString(1) will throw errors.

These three conversions are by far the most common out there, but you can still experiment with other bases. See what each one returns!

And once again, note that this method also converts the number into a string; in effect, that is the sole purpose of toString().

Therefore, before we can work with the converted number (which is a string), we ought to parse it into a number using parseInt() and the respective base of the number.

Following we have a task for you to exercise this number conversion logic.

Convert the binary string '10110' into hexadecimal representation (as a string), and save the result in a variable hexNum.

The following code has been set up for you to start with:

var binNum = '10110';
var hexNum = // put the result here

Note that the final result should be a string.

First we'll need to parse binNum into a number before we can convert this number into a hexadecimal number string.

To parse binNum, we'll use parseInt(binNum, 2). Then, to convert its output into hexadecimal, we'll use toString(16).

Combining both these functions, we have the following code:

var binNum = '10110';
var hexNum = parseInt(binNum, 2).toString(16); // '16'

hexNum turns out to be '16' which represents the decimal number 22. This is correct — the binary string '10110' also represents 22 in decimal format.