JavaScript math, round to two decimal places

Smudger picture Smudger · Apr 2, 2013 · Viewed 654.7k times · Source

I have the following JavaScript syntax:

var discount = Math.round(100 - (price / listprice) * 100);

This rounds up to the whole number. How can I return the result with two decimal places?

Answer

Rick Calder picture Rick Calder · Apr 2, 2013

NOTE - See Edit 4 if 3 digit precision is important

var discount = (price / listprice).toFixed(2);

toFixed will round up or down for you depending on the values beyond 2 decimals.

Example: http://jsfiddle.net/calder12/tv9HY/

Documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed

Edit - As mentioned by others this converts the result to a string. To avoid this:

var discount = +((price / listprice).toFixed(2));

Edit 2- As also mentioned in the comments this function fails in some precision, in the case of 1.005 for example it will return 1.00 instead of 1.01. If accuracy to this degree is important I've found this answer: https://stackoverflow.com/a/32605063/1726511 Which seems to work well with all the tests I've tried.

There is one minor modification required though, the function in the answer linked above returns whole numbers when it rounds to one, so for example 99.004 will return 99 instead of 99.00 which isn't ideal for displaying prices.

Edit 3 - Seems having the toFixed on the actual return was STILL screwing up some numbers, this final edit appears to work. Geez so many reworks!

var discount = roundTo((price / listprice), 2);

function roundTo(n, digits) {
  if (digits === undefined) {
    digits = 0;
  }

  var multiplicator = Math.pow(10, digits);
  n = parseFloat((n * multiplicator).toFixed(11));
  var test =(Math.round(n) / multiplicator);
  return +(test.toFixed(digits));
}

See Fiddle example here: https://jsfiddle.net/calder12/3Lbhfy5s/

Edit 4 - You guys are killing me. Edit 3 fails on negative numbers, without digging into why it's just easier to deal with turning a negative number positive before doing the rounding, then turning it back before returning the result.

function roundTo(n, digits) {
    var negative = false;
    if (digits === undefined) {
        digits = 0;
    }
    if (n < 0) {
        negative = true;
        n = n * -1;
    }
    var multiplicator = Math.pow(10, digits);
    n = parseFloat((n * multiplicator).toFixed(11));
    n = (Math.round(n) / multiplicator).toFixed(digits);
    if (negative) {
        n = (n * -1).toFixed(digits);
    }
    return n;
}

Fiddle: https://jsfiddle.net/3Lbhfy5s/79/