In this article, we’ll explore some of the missing math methods in JavaScript and how we can write functions for them.

The JavaScript Math object contains some really useful and powerful mathematical operations that can be used in web development, but it lacks many important operations that most other languages provide (such as Haskell, which has a huge number of them).

Here are quick links to each one:

Missing Math Methods in JavaScript: Sum

You may remember from school that “sum” is a synonym for “add”. For example, if we sum the numbers 1, 2, and 3, it really means 1 + 2 + 3.

Our sum function will involve summing all the values in an array.

There are two ways of writing this function: we could use a for loop, or we could use the reduce function. If you’d like to re-familiarize yourself with the reduce function, you can read about using map() and reduce() in JavaScript.

Using a for loop:

function sum(array){
    let total = 0
    for(let count = 0; count < array.length; count++){
        total = total + array[count]
    }
    return total
}

Using the reduce function:

function sum(array){
    return array.reduce((sum, number) => sum + number, 0)
}

Both functions work in exactly the same way (the reduce function is just an inbuilt for loop), and will return the same number (given the same array). But the reduce function is much neater.

So, for example:

sum([1,2,3,4]) === 10 

sum([2,4,6,8]) === 20 

Being able to sum a list of numbers is perhaps the most useful and most needed “missing” math operation from the JavaScript Math object. Again, a sum function works as a great checking tool. For example, in a Sudoku we can check if the user has no repeats in that column or row by checking that the column/row adds up to 45 (1 + 2 + 3 + 4 +…+ 9). The function would also work really well in an online shopping app, if we wanted to work out the total bill — assuming all the prices are stored in an array.

Following the shopping app example, here’s an example of how we could use it in our code:

const prices = [2.80, 6.10, 1.50, 1.00, 8.99, 2.99]

function totalCost(prices){
    return prices.reduce((sum, item) => sum + item, 0)
}

Missing Math Methods in JavaScript: Product

Our product function will work in a similar way to the sum function, except that, instead of adding all the numbers in a list, we’ll multiply them.

Once again, we could use a for loop almost identically to the first sum function:

function product(array){
    let total = 1
    for(let count = 0; count < array.length; count++){
        total = total * array[count]
    }
    return total
}

Note that we initialize the total variable with 1 instead of 0, as otherwise we would always end up with a total of 0.

But the reduce function still works in this case and is still a much neater way of writing the function:

function product(array){
    return array.reduce((total, num) => total*num, 1)
}

Here are some examples:

product([2,5,8,6]) === 480 

product([3,7,10,2]) === 420 

The uses of this function may not seem obvious, but I’ve found they’re very useful when trying to enact multiple conversions within one calculation. For example, if you wanted to find the price in dollars of ten packs of apples (each kilogram pack at $1.50), rather than having a huge multiplication sum, it would be more efficient to have all the values stored in an array and use the product function we’ve just written.

An example of the array would be of this format:

const pricePerKg = 1.50
const numberOfKg = 10
const conversionRate = 1.16
const conversion = [1.50, 10, 1.16]

const USprice = product([pricePerKg,numberOfKg,conversionRate])

Missing Math Methods in JavaScript: Odd and Even

These functions will accept a number, which could be in the form of an array length, and return true or false depending on whether the number is odd or even.

For a number to be even, it must be divisible by two, and for a number to be odd, it’s the opposite and isn’t divisible by two. This will be the key part to the functions.

Haskell, for example, has these functions inbuilt, which makes things much easier, especially as you can just write this:

even 29
<< false

odd 29
<< true

Ruby, on the other hand, provides these functions as methods. This is still much easier to write:

29.even?
<< false

29.odd?
<< true

The simplest way to write these functions in JavaScript is to use the remainder operator, %. This returns the remainder when a number is divided by another number. For example:

11 % 3 === 2 

Here’s an example of what our even function could look like:

function even(number){
    return number % 2 === 0
}

As we can see, we have an even function that takes a number as its parameter and returns a Boolean value based on the condition:

number % 2 === 0

When the number is divided by two, if the remainder is equal to zero, we know it’s divisible by two and true will be returned. For example:

even(6) === true

even (9) === false

Here’s an example of what our odd function could look like:

function odd(number){
    return number % 2 !== 0
}

The two functions are very similar: a number is taken as a parameter and a Boolean value is returned based on the condition:

number % 2 !== 0

If the remainder of the number divided by two isn’t equal to zero, the number is odd and true will be returned. For example:

odd(7) === true

odd(114) === false 

Being able to check whether a number is odd or even is vital, and it’s remarkably simple. It may not seem so important at first, but it can work as a great input validation technique — for example, with array lengths, or simply by checking the winner of a two-player game. You can keep track of how many rounds have been played, and if the number is odd, player 1 wins, and if it’s even, player 2 wins — presuming the first round is counted 1.

These functions are interchangeable, and we’ll most likely only need to use one. However, having the two functions can make it much easier to keep track of true or false logic, especially in big chunks of code.

Here’s how we can code the example above:

function checkWinner(gamesPlayed){
    let winner
    if(odd(gamesPlayed)){
        winner = "player1"
    }
    else{
        winner = "player2"
    }
    return winner
}

Missing Math Methods in JavaScript: triangleNumber

Triangle numbers sound a lot more fancy than they actually are. They’re simply the sum of all the integers up until a certain number.

For example, this is the fifth triangle number: 5 + 4 + 3 + 2 + 1 = 15.

This links back to our previous example of the Sudoku. We want to check that all the digits are unique, and we can do this by checking that they match the result of 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9. This, of course, is the ninth triangle number!

We could, of course, write the function using a for loop, in a way like this:

function triangleNumber(number){
    let sum = 0
    for(let i=1; i < number + 1; i++){
        sum = sum + i
    }
    return sum
}

However, this would be a very inefficient decision, because there’s a very simple formula for calculating triangle numbers: 0.5 x (number) x (number + 1).

So, the most efficient version of our function should look like this:

function triangleNumber(number){
    return 0.5 * number * (number + 1)
}

Here are some of examples of how we’d use it:

triangleNumber(7) === 28 

triangleNumber(123) === 7626 

Missing Math Methods in JavaScript: Factorial

The factorial of a natural number (any whole number strictly greater than 0) is the product of all numbers less than or equal to that number. For example: 3 factorial (denoted by 3!) is 3 x 2 x 1 = 6.

Similar to the sum and product functions, there are two ways of creating our factorial function: by using a for loop, and by using recursion. If you haven’t met recursive algorithms before, they’re essentially functions that call themselves repeatedly until they reach a “base case”. You can read more about them in “Recursion in Functional JavaScript”.

Here’s how we can create our factorial function using a for loop:

function factorial(number){
  let total = 1
  for (let i = 1; i < number+1; i++){
    total = total * i
  }
  return total
}

This function loops through all the numbers from 1 to the number (incrementing with each pass) and multiplies the total by each number, before returning the final total (the number factorial).

Here’s how we can create our factorial function using recursion:

function factorial(number){
  if (number <= 0){
    return 1
  }
  else{
    return number * factorial(number - 1)
  }
}

In this function, our base case is zero, since 0! is surprisingly one (the proof to this is actually very interesting). This means that, as the number passes through the function, so long as it’s not zero, it will multiply itself by factorial(number - 1).

To help understand exactly what this function is doing at each pass, it might help to trace the algorithm. Here’s the algorithm traced with 3:

factorial(3) === 3*factorial(2) === 3*2*factorial(1) === 3*2*1*factorial(0) === 3*2*1*1 === 3*2*1 === 6

Either way, both functions will return the same value. For example:

factorial(5) === 120 

Missing Math Methods in JavaScript: Factors

Factors come in pairs, and each pair multiplies together to form the original number. For example:

  • The factors of 10 are: 1 and 10; 2 and 5.
  • The factors of 18 are: 1 and 18; 2 and 9; 3 and 6.

We want our factors function to accept a number, and return an array of all its factors. There are many ways to write this function, but the simplest way is to use an imperative approach, such as this:

function factors(number){
    let factorsList = []
    for(let count = 1; count < number+1; count++){
        if(number % count === 0){
            factorsList.push(count)
        }
    }
    return factorsList
}

Firstly, we create our array — leaving it empty to start with. We then use a for loop to pass through every integer from 1 to the number itself, and at each pass we check whether the number is divisible by the integer (or count in this case).

As you can see, to check the divisibility, we use the mod sign again. And if the number is divisible by the integer, it’s a factor and can be pushed into our array.

The array is then returned, and every time we run the function, an array of factors will be returned in ascending order. For example:

factors(50) === [1,2,5,10,25,50]

Finding the factors of a number can be incredibly useful, particularly when you need to formulate groups — such as in online gaming, when you need an equal number of users in each team. For example, if you had 20 users and each team needed 10 players, you’d be able to use a factors function to match the 10 with two teams. Similarly, if each team needed four players, you could use the factors function to match the four into five teams.

In practice, it may look like this:

function createTeams(numberOfPlayers, numberOfTeams){
    let playersInEachTeam
    if(factors(numberOfPlayers).includes(numberOfTeams)){
        playersInEachTeam = numberOfPlayers / numberOfTeams
    }
    else{
        playersInEachTeam = "wait for more players"
    }
    return playersInEachTeam
}

Missing Math Methods in JavaScript: isPrime

This is one of the earliest conditions that you learn in school, and yet it’s not often used in day-to-day life. In a nutshell, a number is prime if it has two distinct factors, which are always one and itself. The prime numbers begin: 2, 3, 5, 7, 11, 13, 17, 19 … and so on to infinity.

It might initially seem like a complex function — and it may indeed be so if we hadn’t just written a very useful factors function. As mentioned, a number is prime if it has two distinct factors, and so our function is as simple as this:

function isPrime(number){
    return factors(number).length === 2
}

This will return a Boolean value based on whether or not the length of the list of its factors is two — in other words, whether it has two factors.

In practice, it will look like this:

isPrime(3) === true

isPrime(76) === false

isPrime(57) === true

Continuing the “grouping users” example from above, if the number of users is prime, we can’t group them equally (unless we only had one group, but this would defeat the object of the example), which means we’ll have to wait for another user to join. So, we could use it in a function such as this:

function addUsers(users){
    if(isPrime(users)){
        wait = true
    }
    else{
        wait = false
    }
}

Missing Math Methods in JavaScript: gcd (Greatest Common Divisor)

Sometimes known as the “highest common factor”, the greatest common divisor operation finds the largest factor that two numbers share.

For example:

  • The GCD of 12 and 15 is 3.
  • The GCD of 8 and 4 is 4.

An easy way of working this out is to list all the factors of each number (using our incredible function above) and compare those lists. However, comparing the lists requires some pretty nifty but also inefficient array manipulation.

But here’s an example anyway:

function gcd(number1, number2){
    let inCommon = []
    for(let i of factors(number1)){
        if(factors(number2).includes(i)){
            inCommon.push(i)
        }
    }
    return inCommon.sort((a,b)=> b - a)[0]
}

Here, we assign an empty array to the variable inCommon and loop through the array of factors of number1 (using our function from before). If the array of factors of number2 contains the item in the current pass, we push it into our inCommon array.

Once we have an array of all the factors the two numbers have in common, we return the first value of the array sorted in descending order. In other words, we return the greatest common divisor.

As you can imagine, if we hadn’t already created the factors function, the code for this would be huge.

A more succinct but harder way of doing this is by using recursion. This is a pretty famous algorithm, called the Euclidean Algorithm:

function gcd(number1, number2){
    if(number2 === 0){
        return number1
    }
    else{
        return gcd(number2, number1%number2)
    }
}

Our base case here is number2 being equal to 0, at which point number1 is the greatest common divisor. Otherwise, the GCD is the GCD of number2 and the remainder of number1 divided by number2.

Again, both functions will return the same thing. For example:

gcd(24, 16) === 8

gcd(75, 1) === 1

Missing Math Methods in JavaScript: lcm (Lowest Common Multiple)

Lowest common multiple works on a similar wavelength to greatest common divisor, but instead finds the smallest integer that both numbers are factors of.

For example:

  • The LCM of 2 and 6 is 6.
  • The LCM of 4 and 15 is 60.

Unfortunately, for this function we can’t just create an array of all the multiples of each number, as this would be an infinite list.

However, there’s a very useful formula that we can use to calculate the lowest common multiple:

(number1 x number2) / the Greatest Common Divisor of the two numbers

To check the formula, you can try it with the example above. LCM of 2 and 6:

(2 x 6)/gcd(2,6) = 12/2 = 6

Luckily for us, we’ve just created a gcd function, so creating this function is remarkably easy:

function lcm(number1, number2){
    return (number1*number2)/gcd(number1, number2)
}

That’s it! All we need to do is return the formula above and it should work:

lcm(12, 9) === 36 

This function may not have any obvious uses, but I’ve often found it great for situations when there are two events occurring at different intervals, which means we could use the LCM to find out when the two events occur at the same time.

For example, if an image is programmed to appear every six seconds and a paragraph of text is programmed to appear every eight seconds, the image and paragraph will both appear together for the first time on the 24th second.

Conclusion

All the functions above can be found on the following CodePen demo, where you can interact with the functions and see them working in practice.

See the Pen
JavaScript’s Missing Math Methods
by SitePoint (@SitePoint)
on CodePen.

However, if you want to save yourself copying in these functions every time you need them, I’ve compiled them (plus a few others) into a mini-library, called JOG-Maths.

Hopefully this has given you some ideas about which math operations you can use beyond the inbuilt JavaScript Math object and the power of math in code!

Related reading:



Source link

Translate »