Course: JavaScript

Progress (0%)

# Exercise: Better Precision

Exercise 10 Easy

Prerequisites for the exercise

1. JavaScript Number Methods
2. All previous chapters

## Objective

Create a function that extends the number method `toPrecision()` to return a stringified number without scientific notation when the exponent is less than 5.

## Description

In the last chapter on JavaScript Number Methods, we saw the `toPrecision()` method.

Let's recall its syntax:

``number.toPrecision(precision)``

It takes an argument `precision` and rounds a given number to the specified significant figure precision.

Shown below are a couple of examples of the method.

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

In the chapter, we also saw that `toPrecision()` has a special return value when the argument passed to it is less than the number of digits in `number`'s integer part. That is, it returns the stringified number in scientific notation.

Consider the snippet below:

``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'
``389520 .toPrecision(4)``
'3.895e+5'

In the first statement, you might expect the return value to be `'100'`, however this isn't the case. Instead, `'1e+2'` is returned.

As you would agree, for small numbers, like `100`, this behavior of `toPrecision()` could be redundant and undesirable.

In this exercise, you have to create a function called `betterPrecision()` that solves this problem.

The function takes in two args, `num` and `precision`, as demonstrated in the partial definition below:

``````function betterPrecision(num, precision) {
// code goes here
}``````

The return value of this function is exactly the same value returned by `num.toPrecision(precision)`, except for when it is in scientific notation and is otherwise easily representable in normal decimal notation.

If the exponent is less than 5, the number could be represented easily in decimal notation.

Shown below are some examples of the function (that you'll be creating) on the values for which `toPrecision()` returns stringified numbers in scientific notation.

``betterPrecision(124, 1)``
'100'
``betterPrecision(124, 2)``
'120'
``betterPrecision(178, 2)``
'180'
``betterPrecision(17000, 1)``
'20000'
``betterPrecision(17000, 2)``
'17000'
``betterPrecision(17000, 3)``
'17000'
``betterPrecision(389520, 4)``
'3.895e+5'

In the last statement, since the exponent is not less than 5, the value returned by `num.toPrecision(precision)` is returned as is by `betterPrecision()` i.e, `'3.895e+5'`.

## Hints

#### Hint 1

Use `indexOf()` on the return value of `num.toPrecision(precision)` to check whether an `'e'` exists in it.

#### Hint 2

Extract the exponent using the `slice()` string method.

#### Hint 3

Use `Number()` to convert the stringified number, which is in scientific notation, to an actual number and then call the `toString()` method on this number to convert it back into a string.

## New file

Inside the directory you created for this course on JavaScript, create a new folder called Exercise-10-Better-Precision and put the .html solution files for this exercise within it.

## Solution

Let's first review what should the function `betterPrecision()` return before moving over to actually define it.

The function is simply an extension to the method `toPrecision()`. It calls `toPrecision()` and returns its value back, except for in one case — when `toPrecision()` returns a stringified number in scientific notation, where the exponent is less than 5. In this case, the number is represented in the normal notation.

An example follows: `num` is `124` and `precision` is `1`. `num.toPrecision(precision)` returns `'1e+2'` with an exponent less than 5. Likewise, the function `betterPrecision()` converts this value into `'100'` and returns it.

Alright, with this in mind let's now see how to accomplish this problem.

We start by calling `toPrecision()` on the provided number with the given precision. The returned value is saved in a local variable `stringifiedNum`:

``````function betterPrecision(num, precision) {
var stringifiedNum = num.toPrecision(precision);
}``````

Next we check whether `stringifiedNum` has the `e` symbol in it — it's only when `e` is there in this string when we would want to tap into it.

``````function betterPrecision(num, precision) {
var stringifiedNum = num.toPrecision(precision);
if (stringifiedNum.indexOf('e') !== -1) {
// code goes here
}
}``````

If `e` is there in `stringifiedNum`, it means that it's followed by the exponent. This exponent is needed to be extracted out from the string and run against another check.

Let's first get done with the extraction and then see the next check.

The extraction works very simply:

1. We slice the string `stringifiedNum` from the index next to the position where `e` occurs, all the way to the end of the string.
2. Then we convert this sliced string into a number using `Number()`.

For this extraction, we'll need to save the value returned by `stringifiedNum.indexOf('e')` so that it could be used again inside the `if` conditional.

Shown below is the code:

``````function betterPrecision(num, precision) {
var stringifiedNum = num.toPrecision(precision);
var index = stringifiedNum.indexOf('e');

if (index !== -1) {
var exp = Number(stringifiedNum.slice(index + 1));
}
}``````

Moving on, with the exponent in hand, we see whether it is less than 5. If it is, we know that this value represents the special case of `toPrecision()`. Hence, it has to be modified and then returned.

What's the modification?

Simply to replace the scientific notation with an equivalent decimal notation.

Alright, time to think....

How to convert a given value. like `'1e+3'` into an equivalent decimal notation, like `'100'` (for this case)?

Well, we first need to use the `Number()` function to convert the stringified number into an actual number and then use the `toString()` method to convert it back into a string.

`Number()` would convert the string into a number and expand the scientific notation, since JavaScript returns numbers in scientific notation only when the exponent is greater than or equal to 7. For instance `'1e+2'` would become `100`.

After this, the `toString()` method converts the number back to a string. This is done to make sure that the return value of `betterPrecision()` is of the same type as the return value of `toPrecision()`.

To boil it down, the number remains in tact, and the exponential form is gone — just as we desired!

Consider the code below where we accomplish this:

``````function betterPrecision(num, precision) {
var stringifiedNum = num.toPrecision(precision);
var index = stringifiedNum.indexOf('e');

if (index !== -1) {
var exp = Number(stringifiedNum.slice(index + 1));
if (exp < 5) {
return Number(stringifiedNum).toString();
}
}

return stringifiedNum;
}``````

Let's now try `betterPrecision()` on a couple of numbers:

``````function betterPrecision(num, precision) {
/* ... */
}

console.log(betterPrecision(124, 1));
console.log(betterPrecision(124, 2));
console.log(betterPrecision(178, 1));``````
100
120
180

Superb!

This completes our exercise.

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

— Bilal Adnan, Founder of Codeguage