How to round to at most 2 decimal places, if necessary

JavascriptRoundingDecimal Point

Javascript Problem Overview


I'd like to round at most two decimal places, but only if necessary.

Input:

10
1.7777777
9.1

Output:

10
1.78
9.1

How can I do this in JavaScript?

Javascript Solutions


Solution 1 - Javascript

Use Math.round() :

Math.round(num * 100) / 100

Or to be more specific and to ensure things like 1.005 round correctly, use Number.EPSILON :

Math.round((num + Number.EPSILON) * 100) / 100

Solution 2 - Javascript

If the value is a text type:

parseFloat("123.456").toFixed(2);

If the value is a number:

var numb = 123.23454;
numb = numb.toFixed(2);

There is a downside that values like 1.5 will give "1.50" as the output. A fix suggested by @minitech:

var numb = 1.5;
numb = +numb.toFixed(2);
// Note the plus sign that drops any "extra" zeroes at the end.
// It changes the result (which is a string) into a number again (think "0 + foo"),
// which means that it uses only as many digits as necessary.

It seems like Math.round is a better solution. But it is not! In some cases it will not round correctly:

Math.round(1.005 * 100)/100 // Returns 1 instead of expected 1.01!

toFixed() will also not round correctly in some cases (tested in Chrome v.55.0.2883.87)!

Examples:

parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.
parseFloat("1.5550").toFixed(2); // Returns 1.55 instead of 1.56.
// However, it will return correct result if you round 1.5551.
parseFloat("1.5551").toFixed(2); // Returns 1.56 as expected.

1.3555.toFixed(3) // Returns 1.355 instead of expected 1.356.
// However, it will return correct result if you round 1.35551.
1.35551.toFixed(2); // Returns 1.36 as expected.

I guess, this is because 1.555 is actually something like float 1.55499994 behind the scenes.

Solution 1 is to use a script with required rounding algorithm, for example:

function roundNumber(num, scale) {
  if(!("" + num).includes("e")) {
    return +(Math.round(num + "e+" + scale)  + "e-" + scale);
  } else {
    var arr = ("" + num).split("e");
    var sig = ""
    if(+arr[1] + scale > 0) {
      sig = "+";
    }
    return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
  }
}

It is also at Plunker.

Note: This is not a universal solution for everyone. There are several different rounding algorithms. Your implementation can be different, and it depends on your requirements. See also Rounding.

Solution 2 is to avoid front end calculations and pull rounded values from the backend server.

Another possible solution, which is not a bulletproof either.

Math.round((num + Number.EPSILON) * 100) / 100

In some cases, when you round a number like 1.3549999999999998, it will return an incorrect result. It should be 1.35, but the result is 1.36.

Solution 3 - Javascript

You can use

function roundToTwo(num) {
    return +(Math.round(num + "e+2")  + "e-2");
}

I found this on MDN. Their way avoids the problem with 1.005 that was mentioned.

roundToTwo(1.005)
1.01
roundToTwo(10)
10
roundToTwo(1.7777777)
1.78
roundToTwo(9.1)
9.1
roundToTwo(1234.5678)
1234.57

Solution 4 - Javascript

MarkG's answer is the correct one. Here's a generic extension for any number of decimal places.

Number.prototype.round = function(places) {
  return +(Math.round(this + "e+" + places)  + "e-" + places);
}

Usage:

var n = 1.7777;    
n.round(2); // 1.78

Unit test:

it.only('should round floats to 2 places', function() {
    
  var cases = [
    { n: 10,      e: 10,    p:2 },
    { n: 1.7777,  e: 1.78,  p:2 },
    { n: 1.005,   e: 1.01,  p:2 },
    { n: 1.005,   e: 1,     p:0 },
    { n: 1.77777, e: 1.8,   p:1 }
  ]
    
  cases.forEach(function(testCase) {
    var r = testCase.n.round(testCase.p);
    assert.equal(r, testCase.e, 'didn\'t get right number');
  });
})

Solution 5 - Javascript

You should use:

Math.round( num * 100 + Number.EPSILON ) / 100

No one seems to be aware of Number.EPSILON.

Also it's worth noting that this is not a JavaScript weirdness like some people stated.

That is simply the way floating point numbers works in a computer. Like 99% of programming languages, JavaScript doesn't have home made floating point numbers; it relies on the CPU/FPU for that. A computer uses binary, and in binary, there isn't any numbers like 0.1, but a mere binary approximation for that. Why? For the same reason than 1/3 cannot be written in decimal: its value is 0.33333333... with an infinity of threes.

Here come Number.EPSILON. That number is the difference between 1 and the next number existing in the double precision floating point numbers. That's it: There is no number between 1 and 1 + Number.EPSILON.

EDIT:

As asked in the comments, let's clarify one thing: adding Number.EPSILON is relevant only when the value to round is the result of an arithmetic operation, as it can swallow some floating point error delta.

It's not useful when the value comes from a direct source (e.g.: literal, user input or sensor).

EDIT (2019):

Like @maganap and some peoples have pointed out, it's best to add Number.EPSILON before multiplying:

Math.round( ( num + Number.EPSILON ) * 100 ) / 100

EDIT (december 2019):

Lately, I use a function similar to this one for comparing numbers epsilon-aware:

const ESPILON_RATE = 1 + Number.EPSILON ;
const ESPILON_ZERO = Number.MIN_VALUE ;

function epsilonEquals( a , b ) {
  if ( Number.isNaN( a ) || Number.isNaN( b ) ) {
    return false ;
  }
  if ( a === 0 || b === 0 ) {
    return a <= b + EPSILON_ZERO && b <= a + EPSILON_ZERO ;
  }
  return a <= b * EPSILON_RATE && b <= a * EPSILON_RATE ;
}

My use-case is an assertion + data validation lib I'm developing for many years.

In fact, in the code I'm using ESPILON_RATE = 1 + 4 * Number.EPSILON and EPSILON_ZERO = 4 * Number.MIN_VALUE (four times the epsilon), because I want an equality checker loose enough for cumulating floating point error.

So far, it looks perfect for me. I hope it will help.

Solution 6 - Javascript

In general, decimal rounding is done by scaling: round(num * p) / p

Naive implementation

Using the following function with halfway numbers, you will get either the upper rounded value as expected, or the lower rounded value sometimes depending on the input.

This inconsistency in rounding may introduce hard to detect bugs in the client code.

function naiveRound(num, decimalPlaces = 0) {
    var p = Math.pow(10, decimalPlaces);
    return Math.round(num * p) / p;
}

console.log( naiveRound(1.245, 2) );  // 1.25 correct (rounded as expected)
console.log( naiveRound(1.255, 2) );  // 1.25 incorrect (should be 1.26)

// testing edge cases
console.log( naiveRound(1.005, 2) );  // 1    incorrect (should be 1.01)
console.log( naiveRound(2.175, 2) );  // 2.17 incorrect (should be 2.18)
console.log( naiveRound(5.015, 2) );  // 5.01 incorrect (should be 5.02)

In order to determine whether a rounding operation involves a midpoint value, the Round function multiplies the original value to be rounded by 10 ** n, where n is the desired number of fractional digits in the return value, and then determines whether the remaining fractional portion of the value is greater than or equal to .5. This "Exact Testing for Equality" with floating-point values are problematic because of the floating-point format's issues with binary representation and precision. This means that any fractional portion of a number that is slightly less than .5 (because of a loss of precision) will not be rounded upward.

In the previous example, 5.015 is a midpoint value if it is to be rounded to two decimal places, the value of 5.015 * 100 is actually 501.49999999999994. Because .49999999999994 is less than .5, it is rounded down to 501 and finally the result is 5.01.

Better implementations

Exponential notation

By converting the number to a string in the exponential notation, positive numbers are rounded as expected. But, be aware that negative numbers round differently than positive numbers.

In fact, it performs what is basically equivalent to "round half up" as the rule, you will see that round(-1.005, 2) evaluates to -1 even though round(1.005, 2) evaluates to 1.01. The lodash _.round method uses this technique.

/**
 * Round half up ('round half towards positive infinity')
 * Negative numbers round differently than positive numbers.
 */
function round(num, decimalPlaces = 0) {
    num = Math.round(num + "e" + decimalPlaces);
    return Number(num + "e" + -decimalPlaces);
}

// test rounding of half
console.log( round(0.5) );  // 1
console.log( round(-0.5) ); // 0

// testing edge cases
console.log( round(1.005, 2) );   // 1.01
console.log( round(2.175, 2) );   // 2.18
console.log( round(5.015, 2) );   // 5.02

console.log( round(-1.005, 2) );  // -1
console.log( round(-2.175, 2) );  // -2.17
console.log( round(-5.015, 2) );  // -5.01

If you want the usual behavior when rounding negative numbers, you would need to convert negative numbers to positive before calling Math.round(), and then convert them back to negative numbers before returning.

// Round half away from zero
function round(num, decimalPlaces = 0) {
    if (num < 0)
        return -round(-num, decimalPlaces);

    num = Math.round(num + "e" + decimalPlaces);
    return Number(num + "e" + -decimalPlaces);
}

Approximate rounding

To correct the rounding problem shown in the previous naiveRound example, we can define a custom rounding function that performs a "nearly equal" test to determine whether a fractional value is sufficiently close to a midpoint value to be subject to midpoint rounding.

// round half away from zero
function round(num, decimalPlaces = 0) {
    if (num < 0)
        return -round(-num, decimalPlaces);
    var p = Math.pow(10, decimalPlaces);
    var n = num * p;
    var f = n - Math.floor(n);
    var e = Number.EPSILON * n;

    // Determine whether this fraction is a midpoint value.
    return (f >= .5 - e) ? Math.ceil(n) / p : Math.floor(n) / p;
}

// test rounding of half
console.log( round(0.5) );  // 1
console.log( round(-0.5) ); // -1

// testing edge cases
console.log( round(1.005, 2) );  // 1.01
console.log( round(2.175, 2) );  // 2.18
console.log( round(5.015, 2) );  // 5.02

console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02

Number.EPSILON

There is a different purely mathematical technique to perform round-to-nearest (using "round half away from zero"), in which epsilon correction is applied before calling the rounding function.

Simply, we add the smallest possible float value (= 1.0 ulp; unit in the last place) to the product before rounding. This moves to the next representable float value, away from zero, thus it will offset the binary round-off error that may occur during the multiplication by 10 ** n.

/**
 * Round half away from zero ('commercial' rounding)
 * Uses correction to offset floating-point inaccuracies.
 * Works symmetrically for positive and negative numbers.
 */
function round(num, decimalPlaces = 0) {
    var p = Math.pow(10, decimalPlaces);
    var n = (num * p) * (1 + Number.EPSILON);
    return Math.round(n) / p;
}

// rounding of half
console.log( round(0.5) );  // 1
console.log( round(-0.5) ); // -1

// testing edge cases
console.log( round(1.005, 2) );  // 1.01
console.log( round(2.175, 2) );  // 2.18
console.log( round(5.015, 2) );  // 5.02

console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02

After adding 1 ulp, the value of 5.015 * 100 which is 501.49999999999994 will be corrected to 501.50000000000006, this will rounded up to 502 and finally the result is 5.02.

Note that the size of a unit in last place ("ulp") is determined by (1) the magnitude of the number and (2) the relative machine epsilon (2^-52). Ulps are relatively larger at numbers with bigger magnitudes than they are at numbers with smaller magnitudes.

Double rounding

Here, we use the toPrecision() method to strip the floating-point round-off errors in the intermediate calculations. Simply, we round to 15 significant figures to strip the round-off error at the 16th significant digit. This technique to preround the result to significant digits is also used by PHP 7 round function.

The value of 5.015 * 100 which is 501.49999999999994 will be rounded first to 15 significant digits as 501.500000000000, then it will rounded up again to 502 and finally the result is 5.02.

// Round half away from zero
function round(num, decimalPlaces = 0) {
    if (num < 0)
        return -round(-num, decimalPlaces);
    var p = Math.pow(10, decimalPlaces);
    var n = (num * p).toPrecision(15);
    return Math.round(n) / p;
}

// rounding of half
console.log( round(0.5) );  // 1
console.log( round(-0.5) ); // -1

// testing edge cases
console.log( round(1.005, 2) );  // 1.01
console.log( round(2.175, 2) );  // 2.18
console.log( round(5.015, 2) );  // 5.02

console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02

Arbitrary-precision JavaScript library - decimal.js

// Round half away from zero
function round(num, decimalPlaces = 0) {
    return new Decimal(num).toDecimalPlaces(decimalPlaces).toNumber();
}

// rounding of half
console.log( round(0.5) );  // 1
console.log( round(-0.5) ); // -1

// testing edge cases
console.log( round(1.005, 2) );  // 1.01
console.log( round(2.175, 2) );  // 2.18
console.log( round(5.015, 2) );  // 5.02

console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02

<script src="https://cdnjs.cloudflare.com/ajax/libs/decimal.js/10.2.1/decimal.js" integrity="sha512-GKse2KVGCCMVBn4riigHjXE8j5hCxYLPXDw8AvcjUtrt+a9TbZFtIKGdArXwYOlZvdmkhQLWQ46ZE3Q1RIa7uQ==" crossorigin="anonymous"></script>

Solution 1: string in exponential notation

Inspired by the solution provided by KFish here: https://stackoverflow.com/a/55521592/4208440

A simple drop in solution that provides accurate decimal rounding, flooring, and ceiling to a specific number of decimal places without adding a whole library. It treats floats more like decimals by fixing the binary rounding issues to avoid unexpected results: for example, floor((0.1+0.7)*10) will return the expected result 8.

Numbers are rounded to a specific number of fractional digits. Specifying a negative precision will round to any number of places to the left of the decimal point.

// Solution 1
var DecimalPrecision = (function() {
    if (Math.trunc === undefined) {
        Math.trunc = function(v) {
            return v < 0 ? Math.ceil(v) : Math.floor(v);
        };
    }
    var decimalAdjust = function myself(type, num, decimalPlaces) {
        if (type === 'round' && num < 0)
            return -myself(type, -num, decimalPlaces);
        var shift = function(value, exponent) {
            value = (value + 'e').split('e');
            return +(value[0] + 'e' + (+value[1] + (exponent || 0)));
        };
        var n = shift(num, +decimalPlaces);
        return shift(Math[type](n), -decimalPlaces);
    };
    return {
        // Decimal round (half away from zero)
        round: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces);
        },
        // Decimal ceil
        ceil: function(num, decimalPlaces) {
            return decimalAdjust('ceil', num, decimalPlaces);
        },
        // Decimal floor
        floor: function(num, decimalPlaces) {
            return decimalAdjust('floor', num, decimalPlaces);
        },
        // Decimal trunc
        trunc: function(num, decimalPlaces) {
            return decimalAdjust('trunc', num, decimalPlaces);
        },
        // Format using fixed-point notation
        toFixed: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces).toFixed(decimalPlaces);
        }
    };
})();

// test rounding of half
console.log(DecimalPrecision.round(0.5));  // 1
console.log(DecimalPrecision.round(-0.5)); // -1

// testing very small numbers
console.log(DecimalPrecision.ceil(1e-8, 2) === 0.01);
console.log(DecimalPrecision.floor(1e-8, 2) === 0);

// testing simple cases
console.log(DecimalPrecision.round(5.12, 1) === 5.1);
console.log(DecimalPrecision.round(-5.12, 1) === -5.1);
console.log(DecimalPrecision.ceil(5.12, 1) === 5.2);
console.log(DecimalPrecision.ceil(-5.12, 1) === -5.1);
console.log(DecimalPrecision.floor(5.12, 1) === 5.1);
console.log(DecimalPrecision.floor(-5.12, 1) === -5.2);
console.log(DecimalPrecision.trunc(5.12, 1) === 5.1);
console.log(DecimalPrecision.trunc(-5.12, 1) === -5.1);

// testing edge cases for round
console.log(DecimalPrecision.round(1.005, 2) === 1.01);
console.log(DecimalPrecision.round(39.425, 2) === 39.43);
console.log(DecimalPrecision.round(-1.005, 2) === -1.01);
console.log(DecimalPrecision.round(-39.425, 2) === -39.43);

// testing edge cases for ceil
console.log(DecimalPrecision.ceil(9.13, 2) === 9.13);
console.log(DecimalPrecision.ceil(65.18, 2) === 65.18);
console.log(DecimalPrecision.ceil(-2.26, 2) === -2.26);
console.log(DecimalPrecision.ceil(-18.15, 2) === -18.15);

// testing edge cases for floor
console.log(DecimalPrecision.floor(2.26, 2) === 2.26);
console.log(DecimalPrecision.floor(18.15, 2) === 18.15);
console.log(DecimalPrecision.floor(-9.13, 2) === -9.13);
console.log(DecimalPrecision.floor(-65.18, 2) === -65.18);

// testing edge cases for trunc
console.log(DecimalPrecision.trunc(2.26, 2) === 2.26);
console.log(DecimalPrecision.trunc(18.15, 2) === 18.15);
console.log(DecimalPrecision.trunc(-2.26, 2) === -2.26);
console.log(DecimalPrecision.trunc(-18.15, 2) === -18.15);

// testing round to tens and hundreds
console.log(DecimalPrecision.round(1262.48, -1) === 1260);
console.log(DecimalPrecision.round(1262.48, -2) === 1300);

// testing toFixed()
console.log(DecimalPrecision.toFixed(1.005, 2) === "1.01");

Solution 2: purely mathematical (Number.EPSILON)

This solution avoids any string conversion / manipulation of any kind for performance reasons.

// Solution 2
var DecimalPrecision2 = (function() {
    if (Number.EPSILON === undefined) {
        Number.EPSILON = Math.pow(2, -52);
    }
    if (Math.trunc === undefined) {
        Math.trunc = function(v) {
            return v < 0 ? Math.ceil(v) : Math.floor(v);
        };
    }
    var powers = [        1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,        1e8,  1e9,  1e10, 1e11, 1e12, 1e13, 1e14, 1e15,        1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22    ];
    var intpow10 = function(power) {
        if (power < 0 || power > 22) {
            return Math.pow(10, power);
        }
        return powers[power];
    };
    var isRound = function(num, decimalPlaces) {
        //return decimalPlaces >= 0 &&
        //    +num.toFixed(decimalPlaces) === num;
        var p = intpow10(decimalPlaces);
        return Math.round(num * p) / p === num;
    };
    var decimalAdjust = function(type, num, decimalPlaces) {
        if (type !== 'round' && isRound(num, decimalPlaces || 0))
            return num;
        var p = intpow10(decimalPlaces || 0);
        var n = (num * p) * (1 + Number.EPSILON);
        return Math[type](n) / p;
    };
    return {
        // Decimal round (half away from zero)
        round: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces);
        },
        // Decimal ceil
        ceil: function(num, decimalPlaces) {
            return decimalAdjust('ceil', num, decimalPlaces);
        },
        // Decimal floor
        floor: function(num, decimalPlaces) {
            return decimalAdjust('floor', num, decimalPlaces);
        },
        // Decimal trunc
        trunc: function(num, decimalPlaces) {
            return decimalAdjust('trunc', num, decimalPlaces);
        },
        // Format using fixed-point notation
        toFixed: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces).toFixed(decimalPlaces);
        }
    };
})();

// test rounding of half
console.log(DecimalPrecision2.round(0.5));  // 1
console.log(DecimalPrecision2.round(-0.5)); // -1

// testing very small numbers
console.log(DecimalPrecision2.ceil(1e-8, 2) === 0.01);
console.log(DecimalPrecision2.floor(1e-8, 2) === 0);

// testing simple cases
console.log(DecimalPrecision2.round(5.12, 1) === 5.1);
console.log(DecimalPrecision2.round(-5.12, 1) === -5.1);
console.log(DecimalPrecision2.ceil(5.12, 1) === 5.2);
console.log(DecimalPrecision2.ceil(-5.12, 1) === -5.1);
console.log(DecimalPrecision2.floor(5.12, 1) === 5.1);
console.log(DecimalPrecision2.floor(-5.12, 1) === -5.2);
console.log(DecimalPrecision2.trunc(5.12, 1) === 5.1);
console.log(DecimalPrecision2.trunc(-5.12, 1) === -5.1);

// testing edge cases for round
console.log(DecimalPrecision2.round(1.005, 2) === 1.01);
console.log(DecimalPrecision2.round(39.425, 2) === 39.43);
console.log(DecimalPrecision2.round(-1.005, 2) === -1.01);
console.log(DecimalPrecision2.round(-39.425, 2) === -39.43);

// testing edge cases for ceil
console.log(DecimalPrecision2.ceil(9.13, 2) === 9.13);
console.log(DecimalPrecision2.ceil(65.18, 2) === 65.18);
console.log(DecimalPrecision2.ceil(-2.26, 2) === -2.26);
console.log(DecimalPrecision2.ceil(-18.15, 2) === -18.15);

// testing edge cases for floor
console.log(DecimalPrecision2.floor(2.26, 2) === 2.26);
console.log(DecimalPrecision2.floor(18.15, 2) === 18.15);
console.log(DecimalPrecision2.floor(-9.13, 2) === -9.13);
console.log(DecimalPrecision2.floor(-65.18, 2) === -65.18);

// testing edge cases for trunc
console.log(DecimalPrecision2.trunc(2.26, 2) === 2.26);
console.log(DecimalPrecision2.trunc(18.15, 2) === 18.15);
console.log(DecimalPrecision2.trunc(-2.26, 2) === -2.26);
console.log(DecimalPrecision2.trunc(-18.15, 2) === -18.15);

// testing round to tens and hundreds
console.log(DecimalPrecision2.round(1262.48, -1) === 1260);
console.log(DecimalPrecision2.round(1262.48, -2) === 1300);

// testing toFixed()
console.log(DecimalPrecision2.toFixed(1.005, 2) === "1.01");

Solution 3: double rounding

This solution uses the toPrecision() method to strip the floating-point round-off errors.

// Solution 3
var DecimalPrecision3 = (function() {
    if (Math.trunc === undefined) {
        Math.trunc = function(v) {
            return v < 0 ? Math.ceil(v) : Math.floor(v);
        };
    }
    var powers = [        1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,        1e8,  1e9,  1e10, 1e11, 1e12, 1e13, 1e14, 1e15,        1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22    ];
    var intpow10 = function(power) {
        if (power < 0 || power > 22) {
            return Math.pow(10, power);
        }
        return powers[power];
    };
    // Eliminate binary floating-point inaccuracies.
    var stripError = function(num) {
        if (Number.isInteger(num))
            return num;
        return parseFloat(num.toPrecision(15));
    };
    var decimalAdjust = function myself(type, num, decimalPlaces) {
        if (type === 'round' && num < 0)
            return -myself(type, -num, decimalPlaces);
        var p = intpow10(decimalPlaces || 0);
        var n = stripError(num * p);
        return Math[type](n) / p;
    };
    return {
        // Decimal round (half away from zero)
        round: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces);
        },
        // Decimal ceil
        ceil: function(num, decimalPlaces) {
            return decimalAdjust('ceil', num, decimalPlaces);
        },
        // Decimal floor
        floor: function(num, decimalPlaces) {
            return decimalAdjust('floor', num, decimalPlaces);
        },
        // Decimal trunc
        trunc: function(num, decimalPlaces) {
            return decimalAdjust('trunc', num, decimalPlaces);
        },
        // Format using fixed-point notation
        toFixed: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces).toFixed(decimalPlaces);
        }
    };
})();

// test rounding of half
console.log(DecimalPrecision3.round(0.5));  // 1
console.log(DecimalPrecision3.round(-0.5)); // -1

// testing very small numbers
console.log(DecimalPrecision3.ceil(1e-8, 2) === 0.01);
console.log(DecimalPrecision3.floor(1e-8, 2) === 0);

// testing simple cases
console.log(DecimalPrecision3.round(5.12, 1) === 5.1);
console.log(DecimalPrecision3.round(-5.12, 1) === -5.1);
console.log(DecimalPrecision3.ceil(5.12, 1) === 5.2);
console.log(DecimalPrecision3.ceil(-5.12, 1) === -5.1);
console.log(DecimalPrecision3.floor(5.12, 1) === 5.1);
console.log(DecimalPrecision3.floor(-5.12, 1) === -5.2);
console.log(DecimalPrecision3.trunc(5.12, 1) === 5.1);
console.log(DecimalPrecision3.trunc(-5.12, 1) === -5.1);

// testing edge cases for round
console.log(DecimalPrecision3.round(1.005, 2) === 1.01);
console.log(DecimalPrecision3.round(39.425, 2) === 39.43);
console.log(DecimalPrecision3.round(-1.005, 2) === -1.01);
console.log(DecimalPrecision3.round(-39.425, 2) === -39.43);

// testing edge cases for ceil
console.log(DecimalPrecision3.ceil(9.13, 2) === 9.13);
console.log(DecimalPrecision3.ceil(65.18, 2) === 65.18);
console.log(DecimalPrecision3.ceil(-2.26, 2) === -2.26);
console.log(DecimalPrecision3.ceil(-18.15, 2) === -18.15);

// testing edge cases for floor
console.log(DecimalPrecision3.floor(2.26, 2) === 2.26);
console.log(DecimalPrecision3.floor(18.15, 2) === 18.15);
console.log(DecimalPrecision3.floor(-9.13, 2) === -9.13);
console.log(DecimalPrecision3.floor(-65.18, 2) === -65.18);

// testing edge cases for trunc
console.log(DecimalPrecision3.trunc(2.26, 2) === 2.26);
console.log(DecimalPrecision3.trunc(18.15, 2) === 18.15);
console.log(DecimalPrecision3.trunc(-2.26, 2) === -2.26);
console.log(DecimalPrecision3.trunc(-18.15, 2) === -18.15);

// testing round to tens and hundreds
console.log(DecimalPrecision3.round(1262.48, -1) === 1260);
console.log(DecimalPrecision3.round(1262.48, -2) === 1300);

// testing toFixed()
console.log(DecimalPrecision3.toFixed(1.005, 2) === "1.01");

Solution 4: double rounding v2

This solution is just like Solution 3, however it uses a custom toPrecision() function.

// Solution 4
var DecimalPrecision4 = (function() {
    if (Math.trunc === undefined) {
        Math.trunc = function(v) {
            return v < 0 ? Math.ceil(v) : Math.floor(v);
        };
    }
    var powers = [        1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,        1e8,  1e9,  1e10, 1e11, 1e12, 1e13, 1e14, 1e15,        1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22    ];
    var intpow10 = function(power) {
        if (power < 0 || power > 22) {
            return Math.pow(10, power);
        }
        return powers[power];
    };
    var toPrecision = function(num, significantDigits) {
        // Return early for ±0, NaN and Infinity.
        if (!num || !Number.isFinite(num))
            return num;
        // Compute shift of the decimal point (sf - leftSidedDigits).
        var shift = significantDigits - 1 - Math.floor(Math.log10(Math.abs(num)));
        // Return if rounding to the same or higher precision.
        var decimalPlaces = 0;
        for (var p = 1; num != Math.round(num * p) / p; p *= 10) decimalPlaces++;
        if (shift >= decimalPlaces)
            return num;
        // Round to "shift" fractional digits
        var scale = intpow10(Math.abs(shift));
        return shift > 0 ?
            Math.round(num * scale) / scale :
            Math.round(num / scale) * scale;
    };
    // Eliminate binary floating-point inaccuracies.
    var stripError = function(num) {
        if (Number.isInteger(num))
            return num;
        return toPrecision(num, 15);
    };
    var decimalAdjust = function myself(type, num, decimalPlaces) {
        if (type === 'round' && num < 0)
            return -myself(type, -num, decimalPlaces);
        var p = intpow10(decimalPlaces || 0);
        var n = stripError(num * p);
        return Math[type](n) / p;
    };
    return {
        // Decimal round (half away from zero)
        round: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces);
        },
        // Decimal ceil
        ceil: function(num, decimalPlaces) {
            return decimalAdjust('ceil', num, decimalPlaces);
        },
        // Decimal floor
        floor: function(num, decimalPlaces) {
            return decimalAdjust('floor', num, decimalPlaces);
        },
        // Decimal trunc
        trunc: function(num, decimalPlaces) {
            return decimalAdjust('trunc', num, decimalPlaces);
        },
        // Format using fixed-point notation
        toFixed: function(num, decimalPlaces) {
            return decimalAdjust('round', num, decimalPlaces).toFixed(decimalPlaces);
        }
    };
})();

// test rounding of half
console.log(DecimalPrecision4.round(0.5));  // 1
console.log(DecimalPrecision4.round(-0.5)); // -1

// testing very small numbers
console.log(DecimalPrecision4.ceil(1e-8, 2) === 0.01);
console.log(DecimalPrecision4.floor(1e-8, 2) === 0);

// testing simple cases
console.log(DecimalPrecision4.round(5.12, 1) === 5.1);
console.log(DecimalPrecision4.round(-5.12, 1) === -5.1);
console.log(DecimalPrecision4.ceil(5.12, 1) === 5.2);
console.log(DecimalPrecision4.ceil(-5.12, 1) === -5.1);
console.log(DecimalPrecision4.floor(5.12, 1) === 5.1);
console.log(DecimalPrecision4.floor(-5.12, 1) === -5.2);
console.log(DecimalPrecision4.trunc(5.12, 1) === 5.1);
console.log(DecimalPrecision4.trunc(-5.12, 1) === -5.1);

// testing edge cases for round
console.log(DecimalPrecision4.round(1.005, 2) === 1.01);
console.log(DecimalPrecision4.round(39.425, 2) === 39.43);
console.log(DecimalPrecision4.round(-1.005, 2) === -1.01);
console.log(DecimalPrecision4.round(-39.425, 2) === -39.43);

// testing edge cases for ceil
console.log(DecimalPrecision4.ceil(9.13, 2) === 9.13);
console.log(DecimalPrecision4.ceil(65.18, 2) === 65.18);
console.log(DecimalPrecision4.ceil(-2.26, 2) === -2.26);
console.log(DecimalPrecision4.ceil(-18.15, 2) === -18.15);

// testing edge cases for floor
console.log(DecimalPrecision4.floor(2.26, 2) === 2.26);
console.log(DecimalPrecision4.floor(18.15, 2) === 18.15);
console.log(DecimalPrecision4.floor(-9.13, 2) === -9.13);
console.log(DecimalPrecision4.floor(-65.18, 2) === -65.18);

// testing edge cases for trunc
console.log(DecimalPrecision4.trunc(2.26, 2) === 2.26);
console.log(DecimalPrecision4.trunc(18.15, 2) === 18.15);
console.log(DecimalPrecision4.trunc(-2.26, 2) === -2.26);
console.log(DecimalPrecision4.trunc(-18.15, 2) === -18.15);

// testing round to tens and hundreds
console.log(DecimalPrecision4.round(1262.48, -1) === 1260);
console.log(DecimalPrecision4.round(1262.48, -2) === 1300);

// testing toFixed()
console.log(DecimalPrecision4.toFixed(1.005, 2) === "1.01");

Benchmarks

http://jsbench.github.io/#31ec3a8b3d22bd840f8e6822e681a3ac

Here is a benchmark comparing the operations per second in the solutions above on Chrome 85.0.4183.83. Obviously all browsers differ, so your mileage may vary.

Benchmark comparison (Note: More is better)

Thanks @Mike for adding a screenshot of the benchmark.

Solution 7 - Javascript

This question is complicated.

Suppose we have a function, roundTo2DP(num), that takes a float as an argument and returns a value rounded to 2 decimal places. What should each of these expressions evaluate to?

  • roundTo2DP(0.014999999999999999)
  • roundTo2DP(0.0150000000000000001)
  • roundTo2DP(0.015)

The 'obvious' answer is that the first example should round to 0.01 (because it's closer to 0.01 than to 0.02) while the other two should round to 0.02 (because 0.0150000000000000001 is closer to 0.02 than to 0.01, and because 0.015 is exactly halfway between them and there is a mathematical convention that such numbers get rounded up).

The catch, which you may have guessed, is that roundTo2DP cannot possibly be implemented to give those obvious answers, because all three numbers passed to it are the same number. IEEE 754 binary floating point numbers (the kind used by JavaScript) can't exactly represent most non-integer numbers, and so all three numeric literals above get rounded to a nearby valid floating point number. This number, as it happens, is exactly

0.01499999999999999944488848768742172978818416595458984375

which is closer to 0.01 than to 0.02.

You can see that all three numbers are the same at your browser console, Node shell, or other JavaScript interpreter. Just compare them:

> 0.014999999999999999 === 0.0150000000000000001
true

So when I write m = 0.0150000000000000001, the exact value of m that I end up with is closer to 0.01 than it is to 0.02. And yet, if I convert m to a String...

> var m = 0.0150000000000000001;
> console.log(String(m));
0.015
> var m = 0.014999999999999999;
> console.log(String(m));
0.015

... I get 0.015, which should round to 0.02, and which is noticeably not the 56-decimal-place number I earlier said that all of these numbers were exactly equal to. So what dark magic is this?

The answer can be found in the ECMAScript specification, in section 7.1.12.1: ToString applied to the Number type. Here the rules for converting some Number m to a String are laid down. The key part is point 5, in which an integer s is generated whose digits will be used in the String representation of m:

> let n, k, and s be integers such that k ≥ 1, 10k-1 ≤ s < 10k, the Number value for s × 10n-k is m, and k is as small as possible. Note that k is the number of digits in the decimal representation of s, that s is not divisible by 10, and that the least significant digit of s is not necessarily uniquely determined by these criteria.

The key part here is the requirement that "k is as small as possible". What that requirement amounts to is a requirement that, given a Number m, the value of String(m) must have the least possible number of digits while still satisfying the requirement that Number(String(m)) === m. Since we already know that 0.015 === 0.0150000000000000001, it's now clear why String(0.0150000000000000001) === '0.015' must be true.

Of course, none of this discussion has directly answered what roundTo2DP(m) should return. If m's exact value is 0.01499999999999999944488848768742172978818416595458984375, but its String representation is '0.015', then what is the correct answer - mathematically, practically, philosophically, or whatever - when we round it to two decimal places?

There is no single correct answer to this. It depends upon your use case. You probably want to respect the String representation and round upwards when:

  • The value being represented is inherently discrete, e.g. an amount of currency in a 3-decimal-place currency like dinars. In this case, the true value of a Number like 0.015 is 0.015, and the 0.0149999999... representation that it gets in binary floating point is a rounding error. (Of course, many will argue, reasonably, that you should use a decimal library for handling such values and never represent them as binary floating point Numbers in the first place.)
  • The value was typed by a user. In this case, again, the exact decimal number entered is more 'true' than the nearest binary floating point representation.

On the other hand, you probably want to respect the binary floating point value and round downwards when your value is from an inherently continuous scale - for instance, if it's a reading from a sensor.

These two approaches require different code. To respect the String representation of the Number, we can (with quite a bit of reasonably subtle code) implement our own rounding that acts directly on the String representation, digit by digit, using the same algorithm you would've used in school when you were taught how to round numbers. Below is an example which respects the OP's requirement of representing the number to 2 decimal places "only when necessary" by stripping trailing zeroes after the decimal point; you may, of course, need to tweak it to your precise needs.

/**
 * Converts num to a decimal string (if it isn't one already) and then rounds it
 * to at most dp decimal places.
 *
 * For explanation of why you'd want to perform rounding operations on a String
 * rather than a Number, see http://stackoverflow.com/a/38676273/1709587
 *
 * @param {(number|string)} num
 * @param {number} dp
 * @return {string}
 */
function roundStringNumberWithoutTrailingZeroes (num, dp) {
    if (arguments.length != 2) throw new Error("2 arguments required");
    
    num = String(num);
    if (num.indexOf('e+') != -1) {
        // Can't round numbers this large because their string representation
        // contains an exponent, like 9.99e+37
        throw new Error("num too large");
    }
    if (num.indexOf('.') == -1) {
        // Nothing to do
        return num;
    }
    
    var parts = num.split('.'),
        beforePoint = parts[0],
        afterPoint = parts[1],
        shouldRoundUp = afterPoint[dp] >= 5,
        finalNumber;
        
    afterPoint = afterPoint.slice(0, dp);
    if (!shouldRoundUp) {
        finalNumber = beforePoint + '.' + afterPoint;
    } else if (/^9+$/.test(afterPoint)) {
        // If we need to round up a number like 1.9999, increment the integer
        // before the decimal point and discard the fractional part.
        finalNumber = Number(beforePoint)+1;
    } else {
        // Starting from the last digit, increment digits until we find one
        // that is not 9, then stop
        var i = dp-1;
        while (true) {
            if (afterPoint[i] == '9') {
                afterPoint = afterPoint.substr(0, i) +
                             '0' +
                             afterPoint.substr(i+1);
                i--;
            } else {
                afterPoint = afterPoint.substr(0, i) +
                             (Number(afterPoint[i]) + 1) +
                             afterPoint.substr(i+1);
                break;
            }
        }
        
        finalNumber = beforePoint + '.' + afterPoint;
    }
    
    // Remove trailing zeroes from fractional part before returning
    return finalNumber.replace(/0+$/, '')
}

Example usage:

> roundStringNumberWithoutTrailingZeroes(1.6, 2)
'1.6'
> roundStringNumberWithoutTrailingZeroes(10000, 2)
'10000'
> roundStringNumberWithoutTrailingZeroes(0.015, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.015000', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(1, 1)
'1'
> roundStringNumberWithoutTrailingZeroes('0.015', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(0.01499999999999999944488848768742172978818416595458984375, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.01499999999999999944488848768742172978818416595458984375', 2)
'0.01'

The function above is probably what you want to use to avoid users ever witnessing numbers that they have entered being rounded wrongly.

(As an alternative, you could also try the round10 library which provides a similarly-behaving function with a wildly different implementation.)

But what if you have the second kind of Number - a value taken from a continuous scale, where there's no reason to think that approximate decimal representations with fewer decimal places are more accurate than those with more? In that case, we don't want to respect the String representation, because that representation (as explained in the spec) is already sort-of-rounded; we don't want to make the mistake of saying "0.014999999...375 rounds up to 0.015, which rounds up to 0.02, so 0.014999999...375 rounds up to 0.02".

Here we can simply use the built-in toFixed method. Note that by calling Number() on the String returned by toFixed, we get a Number whose String representation has no trailing zeroes (thanks to the way JavaScript computes the String representation of a Number, discussed earlier in this answer).

/**
 * Takes a float and rounds it to at most dp decimal places. For example
 *
 *     roundFloatNumberWithoutTrailingZeroes(1.2345, 3)
 *
 * returns 1.234
 *
 * Note that since this treats the value passed to it as a floating point
 * number, it will have counterintuitive results in some cases. For instance,
 * 
 *     roundFloatNumberWithoutTrailingZeroes(0.015, 2)
 *
 * gives 0.01 where 0.02 might be expected. For an explanation of why, see
 * http://stackoverflow.com/a/38676273/1709587. You may want to consider using the
 * roundStringNumberWithoutTrailingZeroes function there instead.
 *
 * @param {number} num
 * @param {number} dp
 * @return {number}
 */
function roundFloatNumberWithoutTrailingZeroes (num, dp) {
    var numToFixedDp = Number(num).toFixed(dp);
    return Number(numToFixedDp);
}

Solution 8 - Javascript

Consider .toFixed() and .toPrecision():

http://www.javascriptkit.com/javatutors/formatnumber.shtml

Solution 9 - Javascript

One can use .toFixed(NumberOfDecimalPlaces).

var str = 10.234.toFixed(2); // => '10.23'
var number = Number(str); // => 10.23

Solution 10 - Javascript

None of the answers found here is correct. stinkycheeseman asked to round up, but you all rounded the number.

To round up, use this:

Math.ceil(num * 100)/100;

Solution 11 - Javascript

Here is a simple way to do it:

Math.round(value * 100) / 100

You might want to go ahead and make a separate function to do it for you though:

function roundToTwo(value) {
    return(Math.round(value * 100) / 100);
}

Then you would simply pass in the value.

You could enhance it to round to any arbitrary number of decimals by adding a second parameter.

function myRound(value, places) {
    var multiplier = Math.pow(10, places);

    return (Math.round(value * multiplier) / multiplier);
}

Solution 12 - Javascript

A precise rounding method. Source: Mozilla

(function(){

    /**
     * Decimal adjustment of a number.
     *
     * @param   {String}    type    The type of adjustment.
     * @param   {Number}    value   The number.
     * @param   {Integer}   exp     The exponent (the 10 logarithm of the adjustment base).
     * @returns {Number}            The adjusted value.
     */
    function decimalAdjust(type, value, exp) {
        // If the exp is undefined or zero...
        if (typeof exp === 'undefined' || +exp === 0) {
            return Math[type](value);
        }
        value = +value;
        exp = +exp;
        // If the value is not a number or the exp is not an integer...
        if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
            return NaN;
        }
        // Shift
        value = value.toString().split('e');
        value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
        // Shift back
        value = value.toString().split('e');
        return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
    }

    // Decimal round
    if (!Math.round10) {
        Math.round10 = function(value, exp) {
            return decimalAdjust('round', value, exp);
        };
    }
    // Decimal floor
    if (!Math.floor10) {
        Math.floor10 = function(value, exp) {
            return decimalAdjust('floor', value, exp);
        };
    }
    // Decimal ceil
    if (!Math.ceil10) {
        Math.ceil10 = function(value, exp) {
            return decimalAdjust('ceil', value, exp);
        };
    }
})();

Examples:

// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50

Solution 13 - Javascript

This may help you:

var result = Math.round(input*100)/100;

For more information, you can have a look at https://stackoverflow.com/questions/566564/javascript-functions-math-roundnum-vs-num-tofixed0-and-browser-inconsistenci

Solution 14 - Javascript

Use this function Number(x).toFixed(2);

Solution 15 - Javascript

+(10).toFixed(2); // = 10
+(10.12345).toFixed(2); // = 10.12

(10).toFixed(2); // = 10.00
(10.12345).toFixed(2); // = 10.12

Solution 16 - Javascript

For me Math.round() was not giving correct answer. I found toFixed(2) works better. Below are examples of both:

console.log(Math.round(43000 / 80000) * 100); // wrong answer

console.log(((43000 / 80000) * 100).toFixed(2)); // correct answer

Solution 17 - Javascript

Try this lightweight solution:

function round(x, digits){
  return parseFloat(x.toFixed(digits))
}

 round(1.222,  2);
 // 1.22
 round(1.222, 10);
 // 1.222

Solution 18 - Javascript

There are a couple of ways to do that. For people like me, Lodash's variant

function round(number, precision) {
    var pair = (number + 'e').split('e')
    var value = Math.round(pair[0] + 'e' + (+pair[1] + precision))
    pair = (value + 'e').split('e')
    return +(pair[0] + 'e' + (+pair[1] - precision))
}

Usage:

round(0.015, 2) // 0.02
round(1.005, 2) // 1.01

If your project uses jQuery or Lodash, you can also find the proper round method in the libraries.

Solution 19 - Javascript

2017
Just use native code .toFixed()

number = 1.2345;
number.toFixed(2) // "1.23"

If you need to be strict and add digits just if needed it can use replace

number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');

Solution 20 - Javascript

If you are using the Lodash library, you can use the round method of Lodash like following.

_.round(number, precision)

For example:

_.round(1.7777777, 2) = 1.78

Solution 21 - Javascript

Since ES6 there is a 'proper' way (without overriding statics and creating workarounds) to do this by using toPrecision

var x = 1.49999999999;
console.log(x.toPrecision(4));
console.log(x.toPrecision(3));
console.log(x.toPrecision(2));

var y = Math.PI;
console.log(y.toPrecision(6));
console.log(y.toPrecision(5));
console.log(y.toPrecision(4));

var z = 222.987654
console.log(z.toPrecision(6));
console.log(z.toPrecision(5));
console.log(z.toPrecision(4));

then you can just parseFloat and zeroes will 'go away'.

console.log(parseFloat((1.4999).toPrecision(3))); console.log(parseFloat((1.005).toPrecision(3))); console.log(parseFloat((1.0051).toPrecision(3)));

It doesn't solve the '1.005 rounding problem' though - since it is intrinsic to how float fractions are being processed.

console.log(1.005 - 0.005);

If you are open to libraries you can use bignumber.js

console.log(1.005 - 0.005);
console.log(new BigNumber(1.005).minus(0.005));

console.log(new BigNumber(1.005).round(4));
console.log(new BigNumber(1.005).round(3));
console.log(new BigNumber(1.005).round(2));
console.log(new BigNumber(1.005).round(1));

<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/2.3.0/bignumber.min.js"></script>

Solution 22 - Javascript

The easiest approach would be to use toFixed and then strip trailing zeros using the Number function:

const number = 15.5;
Number(number.toFixed(2)); // 15.5
const number = 1.7777777;
Number(number.toFixed(2)); // 1.78

Solution 23 - Javascript

MarkG and Lavamantis offered a much better solution than the one that has been accepted. It's a shame they don't get more upvotes!

Here is the function I use to solve the floating point decimals issues also based on MDN. It is even more generic (but less concise) than Lavamantis's solution:

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp  = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}

Use it with:

round(10.8034, 2);      // Returns 10.8
round(1.275, 2);        // Returns 1.28
round(1.27499, 2);      // Returns 1.27
round(1.2345678e+2, 2); // Returns 123.46

Compared to Lavamantis's solution, we can do...

round(1234.5678, -2); // Returns 1200
round("123.45");      // Returns 123

Solution 24 - Javascript

It may work for you,

Math.round(num * 100)/100;

to know the difference between toFixed and round. You can have a look at https://stackoverflow.com/questions/566564/javascript-functions-math-roundnum-vs-num-tofixed0-and-browser-inconsistenci.

Solution 25 - Javascript

One way to achieve such a rounding only if necessary is to use Number.prototype.toLocaleString():

myNumber.toLocaleString('en', {maximumFractionDigits:2, useGrouping:false})

This will provide exactly the output you expect, but as strings. You can still convert those back to numbers if that's not the data type you expect.

Solution 26 - Javascript

This is the simplest, more elegant solution (and I am the best of the world;):

function roundToX(num, X) {    
    return +(Math.round(num + "e+"+X)  + "e-"+X);
}
//roundToX(66.66666666,2) => 66.67
//roundToX(10,2) => 10
//roundToX(10.904,2) => 10.9

Modern syntax alternative with fallback values

const roundToX = (num = 0, X = 20) => +(Math.round(num + `e${X}`)  + `e-${X}`)

Solution 27 - Javascript

var roundUpto = function(number, upto){
    return Number(number.toFixed(upto));
}
roundUpto(0.1464676, 2);

toFixed(2): Here 2 is the number of digits up to which we want to round this number.

Solution 28 - Javascript

See @AmrAli's answer for a more thorough run through and performance breakdown of all the various adaptations of this solution.

var DecimalPrecision = (function(){
        if (Number.EPSILON === undefined) {
            Number.EPSILON = Math.pow(2, -52);
        }
        if(Number.isInteger === undefined){
            Number.isInteger = function(value) {
                return typeof value === 'number' && 
                isFinite(value) && 
                Math.floor(value) === value;
            };
        }
        this.isRound = function(n,p){
            let l = n.toString().split('.')[1].length;
            return (p >= l);
		}
        this.round = function(n, p=2){
            if(Number.isInteger(n) || this.isRound(n,p))
                return n;
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n<0)
                o *= -1;
            return Math.round((n + r) * o) / o;
        }
        this.ceil = function(n, p=2){
            if(Number.isInteger(n) || this.isRound(n,p))
                return n;
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            
            return Math.ceil((n + r) * o) / o;
        }
        this.floor = function(n, p=2){
            if(Number.isInteger(n) || this.isRound(n,p))
                return n;
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            
            return Math.floor((n + r) * o) / o;
        }
        return this;
    })();
    console.log(DecimalPrecision.round(1.005));
    console.log(DecimalPrecision.ceil(1.005));
    console.log(DecimalPrecision.floor(1.005));
    console.log(DecimalPrecision.round(1.0049999));
    console.log(DecimalPrecision.ceil(1.0049999));
    console.log(DecimalPrecision.floor(1.0049999));
    console.log(DecimalPrecision.round(2.175495134384,7));
    console.log(DecimalPrecision.round(2.1753543549,8));
    console.log(DecimalPrecision.round(2.1755465135353,4));
    console.log(DecimalPrecision.ceil(17,4));
    console.log(DecimalPrecision.ceil(17.1,4));
    console.log(DecimalPrecision.ceil(17.1,15));

Solution 29 - Javascript

Easiest way:

+num.toFixed(2)

It converts it to a string, and then back into an integer / float.

Solution 30 - Javascript

Here is a prototype method:

Number.prototype.round = function(places){
	places = Math.pow(10, places); 
    return Math.round(this * places)/places;
}

var yournum = 10.55555;
yournum = yournum.round(2);

Solution 31 - Javascript

Use something like this "parseFloat(parseFloat(value).toFixed(2))"

parseFloat(parseFloat("1.7777777").toFixed(2))-->1.78 
parseFloat(parseFloat("10").toFixed(2))-->10 
parseFloat(parseFloat("9.1").toFixed(2))-->9.1

Solution 32 - Javascript

To not deal with many 0s, use this variant:

Math.round(num * 1e2) / 1e2

Solution 33 - Javascript

Keep type as integer for later sorting or other math operations:

Math.round(1.7777777 * 100)/100

> 1.78

// Round up!
Math.ceil(1.7777777 * 100)/100 

> 1.78

// Round down!
Math.floor(1.7777777 * 100)/100

> 1.77

Or convert to string:

(1.7777777).toFixed(2)

> "1.77"

Solution 34 - Javascript

2022, native, without library, modern browser, clear and readable.

function round(
  value,
  minimumFractionDigits,
  maximumFractionDigits
) {
  const formattedValue = value.toLocaleString('en', {
    useGrouping: false,
    minimumFractionDigits,
    maximumFractionDigits
  })
  return Number(formattedValue)
}

console.log(round(21.891, 2, 3)) // 21.891
console.log(round(21.0001, 0, 1)) // 21.0
console.log(round(1.8, 2)) // 1.80
console.log(round(0.875, 3)) // 0.875

Solution 35 - Javascript

If you happen to already be using the D3.js library, they have a powerful number formatting library.

Rounding specifically is at D3 round.

In your case, the answer is:

> d3.round(1.777777, 2)
1.78

> d3.round(1.7, 2)
1.7

> d3.round(1, 2)
1

Solution 36 - Javascript

A simpler ES6 way is

const round = (x, n) => 
  Number(parseFloat(Math.round(x * Math.pow(10, n)) / Math.pow(10, n)).toFixed(n));

This pattern also returns the precision asked for.

ex:

round(44.7826456, 4)  // yields 44.7826
round(78.12, 4)       // yields 78.12

Solution 37 - Javascript

> parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.

1.55 is the absolute correct result, because there exists no exact representation of 1.555 in the computer. If reading 1.555 it is rounded to the nearest possible value = 1.55499999999999994 (64 bit float). And rounding this number by toFixed(2) results in 1.55.

All other functions provided here give fault result, if the input is 1.55499999999999.

Solution: Append the digit "5" before scanning to rounding up (more exact: rounding away from 0) the number. Do this only, if the number is really a float (has a decimal point).

parseFloat("1.555"+"5").toFixed(2); // Returns 1.56

Solution 38 - Javascript

A different approach is to use a library. Use Lodash:

const _ = require("lodash")
const roundedNumber = _.round(originalNumber, 2)

Solution 39 - Javascript

I reviewed every answer of this post. Here is my take on the matter:

const nbRounds = 7;
const round = (x, n=2) => {
  const precision = Math.pow(10, n)
  return Math.round((x+Number.EPSILON) * precision ) / precision;
}
let i = 0;
while( nbRounds > i++ ) {
  console.log("round(1.00083899, ",i,") > ", round(1.00083899, i))
  console.log("round(1.83999305, ",i,") > ", round(1.83999305, i))
}

Solution 40 - Javascript

Another approach to this:

number = 16.6666666;
console.log(parseFloat(number.toFixed(2)));
"16.67"

number = 16.6;
console.log(parseFloat(number.toFixed(2)));
"16.6"

number = 16;
console.log(parseFloat(number.toFixed(2)));
"16"

.toFixed(2) returns a string with exactly two decimal points, that may or may not be trailing zeros. Doing a parseFloat() will eliminate those trailing zeros.

Solution 41 - Javascript

This did the trick for me (TypeScript):

round(decimal: number, decimalPoints: number): number{
    let roundedValue = Math.round(decimal * Math.pow(10, decimalPoints)) / Math.pow(10, decimalPoints);

    console.log(`Rounded ${decimal} to ${roundedValue}`);
    return roundedValue;
}
Sample output
Rounded 18.339840000000436 to 18.34
Rounded 52.48283999999984 to 52.48
Rounded 57.24612000000036 to 57.25
Rounded 23.068320000000142 to 23.07
Rounded 7.792980000000398 to 7.79
Rounded 31.54157999999981 to 31.54
Rounded 36.79686000000004 to 36.8
Rounded 34.723080000000124 to 34.72
Rounded 8.4375 to 8.44
Rounded 15.666960000000074 to 15.67
Rounded 29.531279999999924 to 29.53
Rounded 8.277420000000006 to 8.28

Solution 42 - Javascript

A simple solution would be use Lodash's ceil function if you want to round up...

_.round(6.001, 2)

gives 6

_.ceil(6.001, 2);

gives 6.01

_.ceil(37.4929, 2);

gives 37.5

_.round(37.4929, 2);

gives 37.49

Solution 43 - Javascript

Based on the chosen answer and the upvoted comment on the same question:

Math.round((num + 0.00001) * 100) / 100

This works for both these examples:

Math.round((1.005 + 0.00001) * 100) / 100

Math.round((1.0049 + 0.00001) * 100) / 100

Solution 44 - Javascript

The mathematical floor and round definitions:

Enter image description here

lead us to

let round= x=> ( x+0.005 - (x+0.005)%0.01 +'' ).replace(/(\...)(.*)/,'$1');

// for a case like 1.384 we need to use a regexp to get only 2 digits after the dot
// and cut off machine-error (epsilon)

console.log(round(10));
console.log(round(1.7777777));
console.log(round(1.7747777));
console.log(round(1.384));

Solution 45 - Javascript

A simple general rounding function could be following:

Steps are:

  1. Multiply the number by (10 to the power of number of decimal place) using Math.pow(10,places).
  2. Round the result to whole integer using Math.Round.
  3. Divide the result back by (10 to the power of number of decimal place) Math.pow(10,places).

Example:

number is: 1.2375 to be rounded to 3 decimal places

  1. 1.2375 * (10^3) ==> 1.2375 * 1000 = 1237.5
  2. Round to integer ==> 1238
  3. Divide 1238 by (10^3) ==> 1238 / 1000 = 1.238

(note: 10^3 means Math.pow(10,3)).

 function numberRoundDecimal(v,n) {
 return Math.round((v+Number.EPSILON)*Math.pow(10,n))/Math.pow(10,n)}


// ------- tests --------
console.log(numberRoundDecimal(-0.024641163062896567,3))  // -0.025
console.log(numberRoundDecimal(0.9993360575508052,3))     // 0.999
console.log(numberRoundDecimal(1.0020739645577939,3))     // 1.002
console.log(numberRoundDecimal(0.975,0))                  // 1
console.log(numberRoundDecimal(0.975,1))                  // 1
console.log(numberRoundDecimal(0.975,2))                  // 0.98
console.log(numberRoundDecimal(1.005,2))                  // 1.01

Solution 46 - Javascript

I've read all the answers, the answers of similar questions and the complexity of the most "good" solutions didn't satisfy me. I don't want to put a huge round function set, or a small one but fails on scientific notation. So, I came up with this function. It may help someone in my situation:

function round(num, dec) {
   const [sv, ev] = num.toString().split('e');
   return Number(Number(Math.round(parseFloat(sv + 'e' + dec)) + 'e-' + dec) + 'e' + (ev || 0));
}

I didn't run any performance test because I will call this just to update the UI of my application. The function gives the following results for a quick test:

// 1/3563143 = 2.806510993243886e-7
round(1/3563143, 2)  // returns `2.81e-7`

round(1.31645, 4)    // returns 1.3165

round(-17.3954, 2)   // returns -17.4

This is enough for me.

Solution 47 - Javascript

I know there are many answers, but most of them have side effect in some specific cases.

Easiest and shortest solution without any side effects is following:

Number((2.3456789).toFixed(2)) // 2.35

It rounds properly and returns number instead of string

console.log(Number((2.345).toFixed(2)))  // 2.35
console.log(Number((2.344).toFixed(2)))  // 2.34
console.log(Number((2).toFixed(2)))      // 2
console.log(Number((-2).toFixed(2)))     // -2
console.log(Number((-2.345).toFixed(2))) // -2.35

console.log(Number((2.345678).toFixed(3))) // 2.346

Solution 48 - Javascript

Try to use the jQuery .number plug-in:

var number = 19.8000000007;
var res = 1 * $.number(number, 2);

Solution 49 - Javascript

You could also override the Math.round function to do the rounding correct and add a parameter for decimals and use it like: Math.round(Number, Decimals). Keep in mind that this overrides the built in component Math.round and giving it another property then it original is.

var round = Math.round;
Math.round = function (value, decimals) {
  decimals = decimals || 0;
  return Number(round(value + 'e' + decimals) + 'e-' + decimals);
}

Then you can simply use it like this:

Math.round(1.005, 2);

https://jsfiddle.net/k5tpq3pd/3/

Solution 50 - Javascript

To round at decimal positions pos (including no decimals) do Math.round(num * Math.pow(10,pos)) / Math.pow(10,pos)

var console = {
 log: function(s) {
  document.getElementById("console").innerHTML += s + "<br/>"
 }
}
var roundDecimals=function(num,pos) {
 return (Math.round(num * Math.pow(10,pos)) / Math.pow(10,pos) );
}
//https://en.wikipedia.org/wiki/Pi
var pi=3.14159265358979323846264338327950288419716939937510;
for(var i=2;i<15;i++) console.log("pi="+roundDecimals(pi,i));
for(var i=15;i>=0;--i) console.log("pi="+roundDecimals(pi,i));

<div id="console" />

Solution 51 - Javascript

I was building a simple tipCalculator and there was a lot of answers here that seemed to overcomplicate the issue. So I found summarizing the issue to be the best way to truly answer this question.

If you want to create a rounded decimal number, first you call toFixed(# of decimal places you want to keep) and then wrap that in a Number().

So the end result:

let amountDue = 286.44;
tip = Number((amountDue * 0.2).toFixed(2));
console.log(tip)  // 57.29 instead of 57.288

Solution 52 - Javascript

The rounding problem can be avoided by using numbers represented in exponential notation.

public roundFinancial(amount: number, decimals: number) {
    return Number(Math.round(Number(`${amount}e${decimals}`)) + `e-${decimals}`);
}

Solution 53 - Javascript

A simple generic solution

const round = (n, dp) => {
  const h = +('1'.padEnd(dp + 1, '0')) // 10 or 100 or 1000 or etc
  return Math.round(n * h) / h
}

console.log('round(2.3454, 3)', round(2.3454, 3)) // 2.345
console.log('round(2.3456, 3)', round(2.3456, 3)) // 2.346
console.log('round(2.3456, 2)', round(2.3456, 2)) // 2.35

Or just use Lodash round which has the same signature - for example, _.round(2.3456, 2)

Solution 54 - Javascript

Another simple solution (without writing any function) may to use toFixed() and then convert to float again:

For example:

var objNumber = 1201203.1256546456;
objNumber = parseFloat(objNumber.toFixed(2))

Solution 55 - Javascript

Here is a function I came up with to do "round up". I used double Math.round to compensate for JavaScript's inaccurate multiplying, so 1.005 will be correctly rounded as 1.01.

function myRound(number, decimalplaces){
    if(decimalplaces > 0){
        var multiply1 = Math.pow(10,(decimalplaces + 4));
        var divide1 = Math.pow(10, decimalplaces);
        return Math.round(Math.round(number * multiply1)/10000 )/divide1;
    }
    if(decimalplaces < 0){
        var divide2 = Math.pow(10, Math.abs(decimalplaces));
        var multiply2 = Math.pow(10, Math.abs(decimalplaces));
        return Math.round(Math.round(number / divide2) * multiply2);
    }
    return Math.round(number);
}

Solution 56 - Javascript

I wrote the following set of functions for myself. Maybe it will help you too.

function float_exponent(number) {
    exponent = 1;
    while (number < 1.0) {
        exponent += 1
        number *= 10
    }
    return exponent;
}
function format_float(number, extra_precision) {
    precision = float_exponent(number) + (extra_precision || 0)
    return number.toFixed(precision).split(/\.?0+$/)[0]
}

Usage:

format_float(1.01); // 1
format_float(1.06); // 1.1
format_float(0.126); // 0.13
format_float(0.000189); // 0.00019

For you case:

format_float(10, 1); // 10
format_float(9.1, 1); // 9.1
format_float(1.77777, 1); // 1.78

Solution 57 - Javascript

Here is the shortest and complete answer:

function round(num, decimals) {
        var n = Math.pow(10, decimals);
        return Math.round( (n * num).toFixed(decimals) )  / n;
};

This also takes care of the example case 1.005 which will return 1.01.

Solution 58 - Javascript

The big challenge on this seemingly simple task is that we want it to yield psychologically expected results even if the input contains minimal rounding errors to start with (not mentioning the errors which will happen within our calculation). If we know that the real result is exactly 1.005, we expect that rounding to two digits yields 1.01, even if the 1.005 is the result of a large computation with loads of rounding errors on the way.

The problem becomes even more obvious when dealing with floor() instead of round(). For example, when cutting everything away after the last two digits behind the dot of 33.3, we would certainly not expect to get 33.29 as a result, but that is what happens:

console.log(Math.floor(33.3 * 100) / 100)

In simple cases, the solution is to perform calculation on strings instead of floating point numbers, and thus avoid rounding errors completely. However, this option fails at the first non-trivial mathematical operation (including most divsions), and it is slow.

When operating on floating point numbers, the solution is to introduce a parameter which names the amount by which we are willing to deviate from the actual computation result, in order to output the psychologically expected result.

var round = function(num, digits = 2, compensateErrors = 2) {
  if (num < 0) {
    return -this.round(-num, digits, compensateErrors);
  }
  const pow = Math.pow(10, digits);
  return (Math.round(num * pow * (1 + compensateErrors * Number.EPSILON)) / pow);
}

/* --- testing --- */

console.log("Edge cases mentioned in this thread:")
var values = [ 0.015, 1.005, 5.555, 156893.145, 362.42499999999995, 1.275, 1.27499, 1.2345678e+2, 2.175, 5.015, 58.9 * 0.15 ];
values.forEach((n) => {
  console.log(n + " -> " + round(n));
  console.log(-n + " -> " + round(-n));
});

console.log("\nFor numbers which are so large that rounding cannot be performed anyway within computation precision, only string-based computation can help.")
console.log("Standard: " + round(1e+19));
console.log("Compensation = 1: " + round(1e+19, 2, 1));
console.log("Effectively no compensation: " + round(1e+19, 2, 0.4));

Note: Internet Explorer does not know Number.EPSILON. If you are in the unhappy position of still having to support it, you can use a shim, or just define the constant yourself for that specific browser family.

Solution 59 - Javascript

The question is to round to two decimals.

Let’s not make this complicated, modifying prototype chain, etc.

Here is one-line solution

let round2dec = num => Math.round(num * 100) / 100;

console.log(round2dec(1.77));
console.log(round2dec(1.774));
console.log(round2dec(1.777));
console.log(round2dec(10));

Solution 60 - Javascript

A slight variation on this is if you need to format a currency amount as either being a whole amount of currency or an amount with fractional currency parts.

For example:

1 should output $1

1.1 should output $1.10

1.01 should output $1.01

Assuming amount is a number:

const formatAmount = (amount) => amount % 1 === 0 ? amount : amount.toFixed(2);

If amount is not a number then use parseFloat(amount) to convert it to a number.

Solution 61 - Javascript

Just for the record, the scaling method could theoretically return Infinity if the number and the digits you want to round to are big enough. In JavaScript that shouldn't be a problem since the maximum number is 1.7976931348623157e+308, but if you're working with really big numbers or a lot of decimal places you could try this function instead:

Number.prototype.roundTo = function(digits)
{
    var str = this.toString();
    var split = this.toString().split('e');
    var scientific = split.length > 1;
    var index;
    if (scientific)
    {
        str = split[0];
        var decimal = str.split('.');
        if (decimal.length < 2)
            return this;
        index = decimal[0].length + 1 + digits;
    }
    else
        index = Math.floor(this).toString().length + 1 + digits;
    if (str.length <= index)
        return this;
    var digit = str[index + 1];
    var num = Number.parseFloat(str.substring(0, index));
    if (digit >= 5)
    {
        var extra = Math.pow(10, -digits);
        return this < 0 ? num - extra : num + extra;
    }
    if (scientific)
        num += "e" + split[1];
    return num;
}

Solution 62 - Javascript

Starting from the example proposed over the precisionRound that I found on MDN (that event for 1.005 returns 1 and not 1.01), I write a custom precisionRound that manage a random precision number and for 1.005 returns 1.01.

This is the function:

function precisionRound(number, precision)
{
  if(precision < 0)
  {
    var factor = Math.pow(10, precision);
    return Math.round(number * factor) / factor;
  }
  else
    return +(Math.round(number + "e+"+precision)  + "e-"+precision);
}

console.log(precisionRound(1234.5678, 1));  // output: 1234.6
console.log(precisionRound(1234.5678, -1)); // output: 1230
console.log(precisionRound(1.005, 2));      // output: 1.01
console.log(precisionRound(1.0005, 2));     // output: 1
console.log(precisionRound(1.0005, 3));     // output: 1.001
console.log(precisionRound(1.0005, 4));     // output: 1.0005

For TypeScript:

public static precisionRound(number: number, precision: number)
{
  if (precision < 0)
  {
    let factor = Math.pow(10, precision);
    return Math.round(number * factor) / factor;
  }
  else
    return +(Math.round(Number(number + "e+" + precision)) +
      "e-" + precision);
}

Solution 63 - Javascript

From the existing answers I found another solution which seems to work great, which also works with sending in a string and eliminates trailing zeros.

function roundToDecimal(string, decimals) {
    return parseFloat(parseFloat(string).toFixed(decimals));
}

It doesn't take in to account if you send in some bull.. like "apa" though. Or it will probably throw an error which I think is the proper way anyway, it's never good to hide errors that should be fixed (by the calling function).

Solution 64 - Javascript

This worked pretty well for me when wanting to always round up to a certain decimal. The key here is that we will always be rounding up with the Math.ceil function.

You could conditionally select ceil or floor if needed.

     /**
     * Possibility to lose precision at large numbers
     * @param number
     * @returns Number number
     */
    var roundUpToNearestHundredth = function(number) {

        // Ensure that we use high precision Number
        number = Number(number);

        // Save the original number so when we extract the Hundredth decimal place we don't bit switch or lose precision
        var numberSave = Number(number.toFixed(0));

        // Remove the "integer" values off the top of the number
        number = number - numberSave;

        // Get the Hundredth decimal places
        number *= 100;

        // Ceil the decimals.  Therefore .15000001 will equal .151, etc.
        number = Math.ceil(number);

        // Put the decimals back into their correct spot
        number /= 100;

        // Add the "integer" back onto the number
        return number + numberSave;

    };

console.log(roundUpToNearestHundredth(6132423.1200000000001))

Solution 65 - Javascript

Here's my solution to this problem:

function roundNumber(number, precision = 0) {
var num = number.toString().replace(",", "");
var integer, decimal, significantDigit;

if (num.indexOf(".") > 0 && num.substring(num.indexOf(".") + 1).length > precision && precision > 0) {
    integer = parseInt(num).toString();
    decimal = num.substring(num.indexOf(".") + 1);
    significantDigit = Number(decimal.substr(precision, 1));

    if (significantDigit >= 5) {
        decimal = (Number(decimal.substr(0, precision)) + 1).toString();
        return integer + "." + decimal;
    } else {
        decimal = (Number(decimal.substr(0, precision)) + 1).toString();
        return integer + "." + decimal;
    }
}
else if (num.indexOf(".") > 0) {
    integer = parseInt(num).toString();
    decimal = num.substring(num.indexOf(".") + 1);
    significantDigit = num.substring(num.length - 1, 1);

    if (significantDigit >= 5) {
        decimal = (Number(decimal) + 1).toString();
        return integer + "." + decimal;
    } else {            
        return integer + "." + decimal;
    }
} 

return number;
}

Solution 66 - Javascript

As per the answer already given in comments with the link to http://jsfiddle.net/AsRqx/, the following one worked perfectly for me.

function C(num)
{
    return +(Math.round(num + "e+2") + "e-2");
}

function N(num, places)
{
    return +(Math.round(num + "e+" + places) + "e-" + places);
}

C(1.005);

N(1.005, 0);
N(1.005, 1); // Up to 1 decimal places
N(1.005, 2); // Up to 2 decimal places
N(1.005, 3); // Up to 3 decimal places

Solution 67 - Javascript

I just wanted to share my approach, based on previously mentioned answers:

Let's create a function that rounds any given numeric value to a given amount of decimal places:

function roundWDecimals(n, decimals) {
    if (!isNaN(parseFloat(n)) && isFinite(n)) {
        if (typeof(decimals) == typeof(undefined)) {
            decimals = 0;
        }
        var decimalPower = Math.pow(10, decimals);
        return Math.round(parseFloat(n) * decimalPower) / decimalPower;
    }
    return NaN;
}

And introduce a new "round" method for numbers prototype:

Object.defineProperty(Number.prototype, 'round', {
    enumerable: false,
    value: function(decimals) {
        return roundWDecimals(this, decimals);
    }
});

And you can test it:

function roundWDecimals(n, decimals) {
    if (!isNaN(parseFloat(n)) && isFinite(n)) {
        if (typeof(decimals) == typeof(undefined)) {
            decimals = 0;
        }
        var decimalPower = Math.pow(10, decimals);
        return Math.round(parseFloat(n) * decimalPower) / decimalPower;
    }
    return NaN;
}
Object.defineProperty(Number.prototype, 'round', {
    enumerable: false,
    value: function(decimals) {
        return roundWDecimals(this, decimals);
    }
});

var roundables = [
    {num: 10, decimals: 2},
    {num: 1.7777777, decimals: 2},
    {num: 9.1, decimals: 2},
    {num: 55.55, decimals: 1},
    {num: 55.549, decimals: 1},
    {num: 55, decimals: 0},
    {num: 54.9, decimals: 0},
    {num: -55.55, decimals: 1},
    {num: -55.551, decimals: 1},
    {num: -55, decimals: 0},
    {num: 1.005, decimals: 2},
    {num: 1.005, decimals: 2},
    {num: 19.8000000007, decimals: 2},
  ],
  table = '<table border="1"><tr><th>Num</th><th>Decimals</th><th>Result</th></tr>';
$.each(roundables, function() {
  table +=
    '<tr>'+
      '<td>'+this.num+'</td>'+
      '<td>'+this.decimals+'</td>'+
      '<td>'+this.num.round(this.decimals)+'</td>'+
    '</tr>'
  ;
});
table += '</table>';
$('.results').append(table);

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="results"></div>

Solution 68 - Javascript

A generic answer for all browsers and precisions:

function round(num, places) {
    if(!places) {
        return Math.round(num);
    }

    var val = Math.pow(10, places);
    return Math.round(num * val) / val;
}

round(num, 2);

Solution 69 - Javascript

In the Node.js environment I just use the roundTo module:

const roundTo = require('round-to');
...
roundTo(123.4567, 2);

// 123.46

Solution 70 - Javascript

This answer is more about speed.

var precalculatedPrecisions = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10];

function round(num, _prec) {
    _precision = precalculatedPrecisions[_prec]
    return Math.round(num * _precision + 1e-14) / _precision ;
}

jsPerf about this.

Solution 71 - Javascript

I have found this works for all my use cases:

const round = (value, decimalPlaces = 0) => {
    const multiplier = Math.pow(10, decimalPlaces);
    return Math.round(value * multiplier + Number.EPSILON) / multiplier;
};

Keep in mind that is ES6. An ES5 equivalent would be very easy to code though, so I'm not is going to add it.

Solution 72 - Javascript

A helper function where rounging is your default rounding:

let rounding = 4;

let round = (number) => { let multiply = Math.pow(10,rounding);  return Math.round(number*multiply)/multiply};

console.log(round(0.040579431));

=> 0.0406

Solution 73 - Javascript

There is a solution working for all numbers. Give it a try. The expression is given below.

Math.round((num + 0.00001) * 100) / 100. Try Math.round((1.005 + 0.00001) * 100) / 100 and Math.round((1.0049 + 0.00001) * 100) / 100

I recently tested every possible solution and finally arrived at the output after trying almost 10 times.

Here is a screenshot of issue arose during calculations,

Screen capture.

Head over to the amount field. It's returning almost infinite. I gave it a try for the toFixed() method, but it's not working for some cases (i.e., try with pi) and finally derived a solution given above.

Solution 74 - Javascript

A slight modification of this answer that seems to work well.

Function

function roundToStep(value, stepParam) {
   var step = stepParam || 1.0;
   var inv = 1.0 / step;
   return Math.round(value * inv) / inv;
}

Usage

roundToStep(2.55) = 3
roundToStep(2.55, 0.1) = 2.6
roundToStep(2.55, 0.01) = 2.55

Solution 75 - Javascript

This function works for me. You just pass in the number and the places you want to round and it does what it needs to do easily.

round(source, n) {
  let places = Math.pow(10, n);

  return Math.round(source * places) / places;
}

Solution 76 - Javascript

This works correctly with positive, negative and large numbers:

function Round(value) {
    const neat = +(Math.abs(value).toPrecision(15));
    const rounded = Math.round(neat * 100) / 100;

    return rounded * Math.sign(value);
}

//0.244 -> 0.24
//0.245 -> 0.25
//0.246 -> 0.25

//-0.244 -> -0.24
//-0.245 -> -0.25
//-0.246 -> -0.25

Solution 77 - Javascript

Node.js

This did the trick for me on Node.js in a matter of seconds:

npm install math

Source: math.js, Basic usage

Solution 78 - Javascript

Please use the below function if you don't want to round off.

function ConvertToDecimal(num) {
  num = num.toString(); // If it's not already a String
  num = num.slice(0, (num.indexOf(".")) + 3); // With 3 exposing the hundredths place    
alert('M : ' + Number(num)); // If you need it back as a Number     
}

Solution 79 - Javascript

I tried my very own code. Try this:

function AmountDispalyFormat(value) {
    value = value.toFixed(3);
    var amount = value.toString().split('.');
    var result = 0;
    if (amount.length > 1) {
        var secondValue = parseInt(amount[1].toString().slice(0, 2));
        if (amount[1].toString().length > 2) {
            if (parseInt(amount[1].toString().slice(2, 3)) > 4) {
                secondValue++;
                if (secondValue == 100) {
                    amount[0] = parseInt(amount[0]) + 1;
                    secondValue = 0;
                }
            }
        }

        if (secondValue.toString().length == 1) {
            secondValue = "0" + secondValue;
        }
        result = parseFloat(amount[0] + "." + secondValue);
    } else {
        result = parseFloat(amount);
    }
    return result;
}

Solution 80 - Javascript

number=(parseInt((number +0.005)*100))/100;     

add 0.005 if you want to normal round (2 decimals)

8.123 +0.005=> 8.128*100=>812/100=>8.12   

8.126 +0.005=> 8.131*100=>813/100=>8.13   

Solution 81 - Javascript

I created this function, for rounding a number. The value can be a string (ex. '1.005') or a number 1.005 that will be 1 by default and if you specify the decimal to be 2, the result will be 1.01

round(value: string | number, decimals: number | string = "0"): number | null {
	return +( Math.round(Number(value + "e+"+decimals)) + "e-" + decimals);
}

Usage: round(1.005, 2) // 1.01 or Usage: round('1.005', 2) //1.01

Solution 82 - Javascript

The proposed answers, while generally correct, don't consider the precision of the passed in number, which is not expressed as requirement in the original question, but it may be a requirement in case of scientific application where 3 is different from 3.00 (for example) as the number of decimal digits represents the precision of the instrument that have acquired the value or the accuracy of a calculation.

In fact, the proposed answers rounds 3.001 to 3 while by keeping the information about the precision of the number should be 3.00.

Below is a function that takes that in account:

function roundTo(value, decimal) {

    let absValue = Math.abs(value);
    let int = Math.floor(absValue).toString().length;
    let dec = absValue.toString().length - int;
    dec -= (Number.isInteger(absValue) ? 0 : 1);
    return value.toPrecision(int + Math.min(dec, decimal));

}

Solution 83 - Javascript

Use something like this to round up:

num = 519.805;
dp = Math.pow(10, 2);
num = parseFloat(num.toString().concat("1"));
rounded = Math.round((num + Number.EPSILON)* dp)/dp;

As it would deal with numbers falling short where there is only one decimal place to round at the end.

Solution 84 - Javascript

Here's a modified version of astorije's answer that better supports rounding negative values.

// https://stackoverflow.com/a/21323513/384884
// Modified answer from astorije
function round(value, precision) {
    // Ensure precision exists
    if (typeof precision === "undefined" || +precision === 0) {
        // Just do a regular Math.round
        return Math.round(value);
    }

    // Convert the value and precision variables both to numbers
    value = +value;
    precision = +precision;

    // Ensure the value is a number and that precision is usable
    if (isNaN(value) || !(typeof precision === "number" && precision % 1 === 0)) {
        // Return NaN
        return NaN;
    }

    // Get the sign of value
    var signValue = Math.sign(value);

    // Get the absolute value of value
    value = Math.abs(value);

    // Shift
    value = value.toString().split("e");
    value = Math.round(+(value[0] + "e" + (value[1] ? (+value[1] + precision) : precision)));

    // Shift back
    value = value.toString().split("e");
    value = +(value[0] + "e" + (value[1] ? (+value[1] - precision) : -precision));

    // Apply the sign
    value = value * signValue;

    // Return rounded value
    return value;
}

Solution 85 - Javascript

My solution considers the input as a string and uses the algorithm of "mathematical rounding" to n digits: take n digits, and add one if digit n+1 is 5 or more. It also allows specifying negative digits, for example rounding 123.45 to -1 digits is 120. It works with scientific notation (e.g. 1.2e-3), as well. I did not measure its speed and I don't think it was the best performance-wise.

function safeRound( numInput, numPrecision ) {
    const strNumber = numInput.toString().replace( 'E', 'e' );
    const bSign = '+-'.indexOf( strNumber[ 0 ] ) !== -1;
    const strSign = bSign  ?  strNumber[ 0 ]  :  '';
    const numSign = strSign !== '-'  ?  +1  :  -1;
    const ixExponent = ( ixFound => ixFound !== -1  ?  ixFound  :  strNumber.length )( strNumber.indexOf( 'e' ) );
    const strExponent = strNumber.substr( ixExponent + 1 );
    const numExponent = ixExponent !== strNumber.length  ?  Number.parseInt( strExponent )  :  0;
    const ixDecimal = ( ixFound => ixFound !== -1  ?  ixFound  :  ixExponent )( strNumber.indexOf( '.' ) );
    const strInteger = strNumber.substring( !bSign  ?  0  :  1, ixDecimal );
    const strFraction = strNumber.substring( ixDecimal + 1, ixExponent );
    
    const numPrecisionAdjusted = numPrecision + numExponent;
    const strIntegerKeep = strInteger.substring( 0, strInteger.length + Math.min( 0, numPrecisionAdjusted ) ) + '0'.repeat( -Math.min( 0, numPrecisionAdjusted ) );
    const strFractionKeep = strFraction.substring( 0, Math.max( 0, numPrecisionAdjusted ) );
    const strRoundedDown = strSign + ( strIntegerKeep === ''  ?  '0'  :  strIntegerKeep ) + ( strFractionKeep === ''  ?  ''  :  '.' + strFractionKeep ) + ( strExponent === ''  ?  ''  :  'e' + strExponent );
    
    const chRoundUp = 0 <= numPrecisionAdjusted  ?  strFraction.substr( numPrecisionAdjusted, 1 )  :  ( '0' + strInteger ).substr( numPrecisionAdjusted, 1 );
    const bRoundUp = '5' <= chRoundUp && chRoundUp <= '9';
    const numRoundUp = bRoundUp  ?  numSign * Math.pow( 10, -numPrecision )  :  0;
    
    return Number.parseFloat( strRoundedDown ) + numRoundUp;
}

function safeRoundTest( numInput, numPrecision, strExpected ) {
    const strActual = safeRound( numInput, numPrecision ).toString();
    const bPassed = strActual === strExpected;
    console.log( 'numInput', numInput, 'numPrecision', numPrecision, 'strExpected', strExpected, 'strActual', strActual, 'bPassed', bPassed );
    return bPassed  ?  0  :  1;
}

function safeRoundTests() {
    let numFailed = 0;
    numFailed += safeRoundTest( 0, 0, '0' );
    numFailed += safeRoundTest( '0', 0, '0' );
    numFailed += safeRoundTest( '0.1', 0, '0' );
    numFailed += safeRoundTest( '+0.1', 0, '0' );
    numFailed += safeRoundTest( '-0.1', 0, '0' );
    numFailed += safeRoundTest( '0.1', 1, '0.1' );
    numFailed += safeRoundTest( '+0.1', 1, '0.1' );
    numFailed += safeRoundTest( '-0.1', 1, '-0.1' );
    numFailed += safeRoundTest( '0.9', 0, '1' );
    numFailed += safeRoundTest( '+0.9', 0, '1' );
    numFailed += safeRoundTest( '-0.9', 0, '-1' );
    numFailed += safeRoundTest( '0.9', 1, '0.9' );
    numFailed += safeRoundTest( '+0.9', 1, '0.9' );
    numFailed += safeRoundTest( '-0.9', 1, '-0.9' );
    numFailed += safeRoundTest( '0.5', 0, '1' );
    numFailed += safeRoundTest( '+0.5', 0, '1' );
    numFailed += safeRoundTest( '-0.5', 0, '-1' );
    numFailed += safeRoundTest( '0.4999', 0, '0' );
    numFailed += safeRoundTest( '+0.4999', 0, '0' );
    numFailed += safeRoundTest( '-0.4999', 0, '0' );
    numFailed += safeRoundTest( '1.005', 2, '1.01' );
    numFailed += safeRoundTest( '1.00499999999', 2, '1' );
    numFailed += safeRoundTest( '012.3456', -4, '0' );
    numFailed += safeRoundTest( '012.3456', -3, '0' );
    numFailed += safeRoundTest( '012.3456', -2, '0' );
    numFailed += safeRoundTest( '012.3456', -1, '10' );
    numFailed += safeRoundTest( '012.3456', 0, '12' );
    numFailed += safeRoundTest( '012.3456', 1, '12.3' );
    numFailed += safeRoundTest( '012.3456', 2, '12.35' );
    numFailed += safeRoundTest( '012.3456', 3, '12.346' );
    numFailed += safeRoundTest( '012.3456', 4, '12.3456' );
    numFailed += safeRoundTest( '012.3456', 5, '12.3456' );
    numFailed += safeRoundTest( '12.', 0, '12' );
    numFailed += safeRoundTest( '.12', 2, '0.12' );
    numFailed += safeRoundTest( '0e0', 0, '0' );
    numFailed += safeRoundTest( '1.2e3', 0, '1200' );
    numFailed += safeRoundTest( '1.2e+3', 0, '1200' );
    numFailed += safeRoundTest( '1.2e-3', 0, '0' );
    numFailed += safeRoundTest( '1.2e-3', 3, '0.001' );
    numFailed += safeRoundTest( '1.2e-3', 4, '0.0012' );
    numFailed += safeRoundTest( '1.2e-3', 5, '0.0012' );
    numFailed += safeRoundTest( '+12.', 0, '12' );
    numFailed += safeRoundTest( '+.12', 2, '0.12' );
    numFailed += safeRoundTest( '+0e0', 0, '0' );
    numFailed += safeRoundTest( '+1.2e3', 0, '1200' );
    numFailed += safeRoundTest( '+1.2e+3', 0, '1200' );
    numFailed += safeRoundTest( '+1.2e-3', 0, '0' );
    numFailed += safeRoundTest( '+1.2e-3', 3, '0.001' );
    numFailed += safeRoundTest( '+1.2e-3', 4, '0.0012' );
    numFailed += safeRoundTest( '+1.2e-3', 5, '0.0012' );
    numFailed += safeRoundTest( '-12.', 0, '-12' );
    numFailed += safeRoundTest( '-.12', 2, '-0.12' );
    numFailed += safeRoundTest( '-0e0', 0, '0' );
    numFailed += safeRoundTest( '-1.2e3', 0, '-1200' );
    numFailed += safeRoundTest( '-1.2e+3', 0, '-1200' );
    numFailed += safeRoundTest( '-1.2e-3', 0, '0' );
    numFailed += safeRoundTest( '-1.2e-3', 3, '-0.001' );
    numFailed += safeRoundTest( '-1.2e-3', 4, '-0.0012' );
    numFailed += safeRoundTest( '-1.2e-3', 5, '-0.0012' );
    numFailed += safeRoundTest( '9876.543e210', 0, '9.876543e+213' );
    numFailed += safeRoundTest( '9876.543e210', -210, '9.877e+213' );
    numFailed += safeRoundTest( '9876.543e210', -209, '9.8765e+213' );
    numFailed += safeRoundTest( '9876.543e+210', 0, '9.876543e+213' );
    numFailed += safeRoundTest( '9876.543e+210', -210, '9.877e+213' );
    numFailed += safeRoundTest( '9876.543e+210', -209, '9.8765e+213' );
    numFailed += safeRoundTest( '9876.543e-210', 213, '9.876543e-207' );
    numFailed += safeRoundTest( '9876.543e-210', 210, '9.877e-207' );
    numFailed += safeRoundTest( '9876.543e-210', 211, '9.8765e-207' );
    console.log( 'numFailed', numFailed );
}

safeRoundTests();

Solution 86 - Javascript

If you are using Lodash in your project, then just do:

_.round(value, 2);

Solution 87 - Javascript

I still don't think anyone gave him the answer to how to only do the rounding if needed. The easiest way I see to do it is to check if there is even a decimal in the number, like so:

var num = 3.21;
if ( (num+"").indexOf('.') >= 0 ) { //at least assert to string first...
    // whatever code you decide to use to round
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionstinkycheesemanView Question on Stackoverflow
Solution 1 - JavascriptBrian UstasView Answer on Stackoverflow
Solution 2 - JavascriptA KuninView Answer on Stackoverflow
Solution 3 - JavascriptMarkGView Answer on Stackoverflow
Solution 4 - JavascriptLavamantisView Answer on Stackoverflow
Solution 5 - JavascriptcronvelView Answer on Stackoverflow
Solution 6 - JavascriptAmr AliView Answer on Stackoverflow
Solution 7 - JavascriptMark AmeryView Answer on Stackoverflow
Solution 8 - JavascriptAceCorbanView Answer on Stackoverflow
Solution 9 - JavascriptGourav SinglaView Answer on Stackoverflow
Solution 10 - JavascriptmachineaddictView Answer on Stackoverflow
Solution 11 - JavascriptJayDMView Answer on Stackoverflow
Solution 12 - JavascriptuserView Answer on Stackoverflow
Solution 13 - JavascripttottenView Answer on Stackoverflow
Solution 14 - JavascriptHarish.bazeeView Answer on Stackoverflow
Solution 15 - Javascriptuser3711536View Answer on Stackoverflow
Solution 16 - JavascriptVikasdeep SinghView Answer on Stackoverflow
Solution 17 - JavascriptpetermeissnerView Answer on Stackoverflow
Solution 18 - Javascriptstanleyxu2005View Answer on Stackoverflow
Solution 19 - Javascriptpery mimonView Answer on Stackoverflow
Solution 20 - JavascriptMadura PradeepView Answer on Stackoverflow
Solution 21 - JavascriptMatas VaitkeviciusView Answer on Stackoverflow
Solution 22 - JavascriptMarcin WanagoView Answer on Stackoverflow
Solution 23 - JavascriptastorijeView Answer on Stackoverflow
Solution 24 - JavascriptShreedharView Answer on Stackoverflow
Solution 25 - JavascriptJavaromeView Answer on Stackoverflow
Solution 26 - JavascriptSoldeplata SaketosView Answer on Stackoverflow
Solution 27 - JavascriptRitesh DhuriView Answer on Stackoverflow
Solution 28 - JavascriptKFishView Answer on Stackoverflow
Solution 29 - JavascriptbigpotatoView Answer on Stackoverflow
Solution 30 - JavascriptarielfView Answer on Stackoverflow
Solution 31 - JavascriptArulrajView Answer on Stackoverflow
Solution 32 - JavascriptDaniel De LeónView Answer on Stackoverflow
Solution 33 - JavascriptprofimedicaView Answer on Stackoverflow
Solution 34 - JavascriptVictor dlfView Answer on Stackoverflow
Solution 35 - JavascriptScott StaffordView Answer on Stackoverflow
Solution 36 - JavascriptAdam A.View Answer on Stackoverflow
Solution 37 - JavascriptWiimmView Answer on Stackoverflow
Solution 38 - JavascriptCarlos LombardiView Answer on Stackoverflow
Solution 39 - JavascriptAlexandre ELIOTView Answer on Stackoverflow
Solution 40 - JavascriptMarcos LimaView Answer on Stackoverflow
Solution 41 - JavascriptRossView Answer on Stackoverflow
Solution 42 - JavascriptPavithran RavichandiranView Answer on Stackoverflow
Solution 43 - JavascriptFellow StrangerView Answer on Stackoverflow
Solution 44 - JavascriptKamil KiełczewskiView Answer on Stackoverflow
Solution 45 - JavascriptMohsen AlyafeiView Answer on Stackoverflow
Solution 46 - JavascriptsuperkeciView Answer on Stackoverflow
Solution 47 - JavascriptNicoloView Answer on Stackoverflow
Solution 48 - Javascriptuser3447070View Answer on Stackoverflow
Solution 49 - JavascriptArne H. BitubekkView Answer on Stackoverflow
Solution 50 - JavascriptloretoparisiView Answer on Stackoverflow
Solution 51 - JavascriptDenis S DujotaView Answer on Stackoverflow
Solution 52 - JavascriptDmytro MedvidView Answer on Stackoverflow
Solution 53 - Javascriptdanday74View Answer on Stackoverflow
Solution 54 - JavascriptArifur Rahman KhanView Answer on Stackoverflow
Solution 55 - JavascriptAndreiView Answer on Stackoverflow
Solution 56 - JavascriptvsvasyaView Answer on Stackoverflow
Solution 57 - JavascriptmjsView Answer on Stackoverflow
Solution 58 - JavascriptmalamutView Answer on Stackoverflow
Solution 59 - JavascriptSalmanView Answer on Stackoverflow
Solution 60 - JavascriptIbraheemView Answer on Stackoverflow
Solution 61 - JavascriptMartinView Answer on Stackoverflow
Solution 62 - JavascriptMarco BarberoView Answer on Stackoverflow
Solution 63 - JavascriptOZZIEView Answer on Stackoverflow
Solution 64 - Javascriptthecoolestname36View Answer on Stackoverflow
Solution 65 - Javascriptcaliche2000View Answer on Stackoverflow
Solution 66 - JavascriptyadavrView Answer on Stackoverflow
Solution 67 - JavascriptDeeleView Answer on Stackoverflow
Solution 68 - JavascriptRBZView Answer on Stackoverflow
Solution 69 - JavascriptSimon PrickettView Answer on Stackoverflow
Solution 70 - JavascriptalehaView Answer on Stackoverflow
Solution 71 - JavascriptRob EvansView Answer on Stackoverflow
Solution 72 - JavascriptAjsti.pl - Maciej SzewczykView Answer on Stackoverflow
Solution 73 - JavascriptKiran ManiyaView Answer on Stackoverflow
Solution 74 - JavascriptCrashalotView Answer on Stackoverflow
Solution 75 - JavascriptjerryView Answer on Stackoverflow
Solution 76 - JavascriptButsatyView Answer on Stackoverflow
Solution 77 - Javascriptstevek-proView Answer on Stackoverflow
Solution 78 - JavascriptNimeshView Answer on Stackoverflow
Solution 79 - JavascriptSuganth GView Answer on Stackoverflow
Solution 80 - JavascriptElid GarazlicView Answer on Stackoverflow
Solution 81 - JavascriptchriscrosswebView Answer on Stackoverflow
Solution 82 - JavascriptMosè BottaciniView Answer on Stackoverflow
Solution 83 - Javascriptshahroz buttView Answer on Stackoverflow
Solution 84 - JavascriptDeejersView Answer on Stackoverflow
Solution 85 - Javascriptz32a7ulView Answer on Stackoverflow
Solution 86 - JavascriptSjonchheView Answer on Stackoverflow
Solution 87 - JavascriptcoreyavisView Answer on Stackoverflow