How do you round a double value to 2 decimal places in 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

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.

How do you round a double value to 2 decimal places in javascript?
(Note: More is better)

Thanks @Mike for adding a screenshot of the benchmark.

How do you round a double value in JavaScript?

Math. round() is a function used to return the value of a floating-point number rounded to the nearest whole integer. Depending on the supplied float/double, Math. round() either rounds up or down.

How do you round a double to 2 places?

DecimalFormat(“0.00”) We can use DecimalFormat("0.00") to ensure the number always round to 2 decimal places. For DecimalFormat , the default rounding mode is RoundingMode.

How do you round to a certain decimal places in JavaScript?

JavaScript Number toFixed() The toFixed() method converts a number to a string. The toFixed() method rounds the string to a specified number of decimals.