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

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.

View Solution

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.