🤯 New: Coding Assessments Practice your skills on real-world programming challenges

A Guide to Rounding Numbers in JavaScript

    Darren Jones
    Share

    In this article, we’ll explore various ways of rounding numbers in JavaScript. This will include using JavaScript math functions, and other methods for rounding to decimal places. We’ll also cover gotchas to watch out for when rounding numbers.

    JavaScript Rounding

    When dealing with numerical values, we can sometimes perform calculations that end up with fractional parts that need rounding to a whole number — such as when you’re working out an average price, or dealing with random numbers. Thankfully, JavaScript’s Math object provides a number of ways to round numbers to an integer value.

    In our examples, we’ll use two of the most important mathematical constants to demonstrate different types of rounding: Pi, which is the ratio of the circumference of a circle to its diameter, and e, which is the base of natural logarithms and also known as “Euler’s number”. Both of these values are properties of the Math object, but let’s assign them to some variables to make them easier to deal with:

    const PI = Math.PI
    const E = Math.E
    

    Pro tip: you can also make this assignment in a single line using object destructuring:

    const { PI,E } = Math
    

    Now we have these constants defined, let’s take a look at some of the methods for rounding numbers in JavaScript.

    Rounding Numbers in JavaScript with Math.round

    The first method we’ll look at is Math.round. This is the most straightforward option, and simply rounds any number with a decimal part to the nearest integer. It uses this rule: if a number is exactly halfway between two integers, it will be rounded up. For example, 2.5 will round up to 3.

    To use this method, we simply provide the number we want to round as the argument:

    Math.round(2.3) // rounds down because it's closer to 2
    << 2
    
    Math.round(2.921) // rounds up because it's closer to 3
    << 3
    
    Math.round(2.5) // rounds up because it's exactly halfway
    << 3
    
    Math.round(PI)
    << 3
    
    Math.round(E)
    << 3
    

    Math.round() comes in handy if you want to round a number to the nearest integer value. For example, if you were calculating the average score over three tests, you’d add the three scores up and divide by three. This might not result in a whole number, so you’d use Math.round() to round it to the closest value:

    const test1 = 86;
    const test2 = 93;
    const test3 = 95;
    const average = Math.round((test1+test2+test3)/3);
    << 91
    

    Rounding Numbers with Math.floor

    The next method we’ll look at is Math.floor. This always rounds a value down to the integer below (the name implies the number is being pushed down to the floor):

    Math.floor(2.3) // rounds down to 2
    << 2
    
    Math.floor(2.921) // rounds down to 2
    << 2
    
    Math.floor(2.5) // rounds down to 2
    << 2
    
    Math.floor(PI)
    << 3
    
    Math.floor(E)
    << 2
    

    A common use of Math.floor is when creating random integers. Rounding down ensures that the integer will start at zero and that each integer will have an equal chance of being returned. Starting at zero is generally useful, as arrays in JavaScript are zero-indexed, so rounding down will make sure that the first element in the array could be selected. The example below shows how a random element could be selected from an array using Math.floor:

    const fruit = ["🍏","🍌","🍓","🍋","🍐"]
    
    const randomFruit = fruit[Math.floor(Math.random()*fruit.length)]
    << "🍓"
    

    Rounding down using Math.floor in the code above ensures that an index between 0 and 4 is returned, so every element in the array has an equal chance of being selected.

    Rounding Numbers with Math.ceil

    Speaking of rounding up, this is exactly what Math.ceil does. The name comes from ceiling and is the opposite of floor, implying the value is going up. The method works in the same way as all the others. Just provide the number you want to round up as an argument:

    Math.ceil(2.3) // rounds up to 3
    << 3
    
    Math.ceil(2.921) // rounds up to 3
    << 3
    
    Math.ceil(2.5) // rounds up to 3
    << 3
    
    Math.ceil(PI)
    << 4
    
    Math.ceil(E)
    << 3
    

    But when would you need to round a number up? A common usage is if you need to work out how many containers you need for something. For example, say you have a music site that includes playlists, and each playlist has ten songs on it. If somebody uploads 82 songs, you need to work out how many playlists to create. This is done by dividing the number of songs by 10 (the number of songs on each playlist):

    const songsPerPlaylist = 10;
    const numberOfSongs = 82;
    const numberOfPlaylists = numberOfSongs/songsPerPlaylist;
    << 8.2
    

    Using Math.round would round this down to 8 … but then we wouldn’t have a playlist for the last two songs! In cases like this, we always need to round up in order to have an extra container for any remainders:

    const numberOfPlaylists = Math.ceil(numberOfSongs/songsPerPlaylist);
    << 9
    

    Rounding Numbers with Math.trunc

    The next method we’ll look at is Math.trunc. This isn’t strictly speaking a rounding function; it actually truncates the number provided as an argument. It basically just removes the decimal part of the number, leaving just the integer part, as can be seen in the examples below:

    Math.trunc(2.3) // just leaves 2
    << 2
    
    Math.trunc(2.921) // just leaves 2, even though it's closer to 3
    << 2
    
    Math.trunc(2.5) // just leaves 2
    << 2
    
    Math.trunc(PI)
    << 3
    
    Math.trunc(E)
    << 2
    

    At first glance, Math.trunc seems to be identical to Math.floor; certainly the examples given so far all give the same results. These two methods behave differently, however, when a negative value is provided as an argument, as can be seen in the example below:

    Math.floor(-2.3) // rounds DOWN to -3
    << -3
    
    Math.trunc(-2.3) // removes the decimal part, leaving just -2
    << -2
    

    The difference occurs because, when a negative number is rounded down using Math.floor, it goes down to the next lowest integer, whereas truncating a negative value is the equivalent of rounding it up.

    Math.ceil returns the same value as Math.trunc when the argument is a negative number:

    Math.trunc(-2.3) // removes the decimal part, leaving just -2
    << -2
    
    Math.ceil(-2.3) // rounds UP to -2
    << -2
    

    All of these methods can be very useful, but they have the limitation that they always return integer values. What if we want to round a number to a certain number of decimal places or significant figures?

    Rounding Numbers To Decimal Places in JavaScript

    We’ve already seen that Math.round will round numbers to the nearest integer. Unfortunately, the Math object doesn’t provide any methods to round numbers more accurately to a certain number of decimal places. Thankfully, the Number type has a couple of built-in methods that can do this. Let’s take a look at them.

    Rounding to decimal places with Number.toFixed

    This is a number method, which means that it’s called by the number itself. It rounds a decimal number to a given number of decimal places, which is provided as an argument:

    2.4387587.toFixed(2) // rounds to 2 decimal places
    << "2.44"
    

    One thing to note is that the value is returned as a string. You can get around this by wrapping the method call in the Number function, which will convert the result back into a number:

    Number(2.4387587.toFixed(2))
    << 2.44
    

    Something else to watch out for: if you try to apply this method to a number that’s already an integer, you’ll get an error if you just use a single dot to call the method:

    2.toFixed(2)
    << SyntaxError
    

    You can’t call methods on integers using a single dot, because it isn’t clear if the dot is a method call operator or a decimal point. To get around this, you can either place the integer in parentheses or use two dots so that it’s clear that you’re calling a method rather than writing out a number literal with a decimal point:

    (2).toFixed(2)
    << "2.00"
    
    2..toFixed(2)
    << "2.00"
    

    If no argument is provided, the number will be rounded to the nearest integer (but returned as a string):

    PI.toFixed()
    << "3"
    
    E.toFixed()
    << "3"
    

    A common use case for rounding to a set number of decimal places is when dealing with currency — for example, if you want to provide the price of something in US dollars to the nearest cent. Let’s say you had an ecommerce site that was running a promotion of 15% off anything in the shopping cart. The discounted price might need rounding before it’s displayed:

    const item1Price = 2.99
    const item2Price = 4.99
    const item3Price = 6.20
    
    const totalPrice = item1Price + item2Price + item3Price
    const discountedPrice = 0.85 * totalPrice
    << 12.052999999999999
    

    This can easily be fixed using Number.toFixed:

    const discountedPrice = (0.85 * totalPrice).toFixed(2)
    << "12.05"
    

    Note: for more on issues you might face with toFixed(), see Number().toFixed() Rounding Errors: Broken But Fixable.

    Rounding numbers to decimal places with Number.toPrecision

    The Number.toPrecision method works in a similar way to the Number.toFixed method, but it rounds numbers to a fixed number of significant figures.

    If you need a quick reminder of significant figures, it basically means to only use the first non-zero digits. For large numbers, the final answer will also be padded out with zeroes as well. For example, the number 53,863 rounded to two significant figures will become 54,000. This is because 5 and 3 are the first two non-zero digits, and it rounds up because the next digit is 8. We need to add zeroes at the end to ensure the rounded value is a reasonable approximation to the original number.

    You can also round decimals in a similar way. For example, 0.00000623978 will round to 0.0000062 to two significant figures because 6 and 2 are the first non-zero digits and it rounds down because the next digit is 3.

    To use this method, simply call it on the number, providing the number of significant figures as an argument (remember that integers need to be placed in parentheses before calling a method on them):

    (53863).toPrecision(2)
    << "5.4e+4"
    
    0.00000623978.toPrecision(2)
    << 0.0000062"
    

    Note that all values are returned as strings, and exponential notation can be used — such as “5.4e+4” instead of “54000”.

    As before, we can ensure that a number is returned by wrapping the method call in the Number function:

    Number((53863).toPrecision(2))
    << 54000
    

    A common use for rounding to a given number of significant figures is when you’re dealing with large numbers and you’re not sure just how big they’re going to be. For example, say you want to report how many times your latest post has been “liked”, do you round it to the nearest 10, 100 or 1000? In a way, this depends how popular it is; you don’t want to round it to the nearest 100 if it only gets 8 likes, but if it gets thousands of likes then it seems silly to round it to the nearest 10. The solution is to round it to one significant figure:

    const unpopularPost = 8;
    const quitePopularPost = 387;
    const poplularPost = 79671;
    
    Number(unpopularPost.toPrecision(1))
    << 8
    Number(quitePopularPost.toPrecision(1))
    << 400
    Number(poplularPost.toPrecision(1))
    << Number(poplularPost.toPrecision(1))
    << 80000
    

    Problems with Rounding Numbers in JavaScript

    There are a few things to watch out for when rounding numbers in JavaScript (or any programming language, for that matter). As you probably know, computers store all data — including numbers — as a binary representation. JavaScript stores numbers as 32-bit single precision binary values.

    The problem with this is that some base 10 numbers can’t be accurately represented in base 2. This doesn’t usually cause any problems, but it does cause some strange results such as this:

    0.1 + 0.2 === 0.3
    << false
    

    This is because 0.1 and 0.2 can’t be represented exactly in binary, and a slight error is made when adding them up.

    The Math object has another method called fround, which returns the closest number that can be represented using 32-bits. For example, 0.6125 can be represented exactly in binary as 0.101, so this will return the same value:

    Math.fround(0.625)
    << 0.625
    

    But, as we saw above, 0.1 can’t be represented exactly in 32-bits. Math.fround shows us the closest number that can be represented:

    Math.fround(0.1)
    << 0.10000000149011612
    

    As you can see, it’s very close to 0.1, but very slightly higher. In most practical cases, this won’t cause any problems, but it can occasionally cause some strange behavior when you try to round some numbers:

    3.55.toFixed(1) // should round UP to 3.6
    << "3.5"
    

    This happens because the decimal 3.55 can’t be accurately represented in using 32-bits. We can use Math.fround to see how it’s actually represented:

    Math.fround(3.55)
    << 3.549999952316284
    

    As you can see, it’s actually represented by the floating point number 3.549999952316284, which rounds down to 3.5.

    These problems with rounding numbers in JavaScript don’t occur too often, but they’re definitely something you should be aware of if you’re doing a lot of rounding — especially when it’s important that the result is accurate.

    Which Methods Should I Use for Rounding Numbers?

    With all the rounding methods presenting in this rounding roundup, you might be asking which is the best to use. As always, the answer is, “It depends”.

    If you simply want to round a number to the nearest integer, you can’t go far wrong with Math.round, but you should also consider using Math.floor or Math.ceil if you always want to round down or up, regardless of what the decimal part is. And consider using Math.trunc instead if you’re also planning on rounding negative numbers.

    If you need to round to a given number of decimal places or significant figures, you’ll have to use Number.toFixed or Number.toPrecision. But be aware that these two methods are called by the number and return a string.

    You can see an example of all the different types of rounding covered in this article in the following CodePen demo.

    See the Pen
    SitePoint Rounding
    by SitePoint (@SitePoint)
    on CodePen.

    With all these different methods available, you should have no problem rounding numbers from now on.

    If you found this article useful, you may also like these: