Alex Rivera | Logout

Truncate (not round off) decimal numbers in JavaScript

Asked 2011-02-06T10:42:08.843
134

I am trying to truncate decimal numbers to decimal places. Something like this:

5.467   -> 5.46
985.943 -> 985.94

toFixed(2) does just about the right thing, but it rounds off the value. I don't need the value rounded off. Is this possible in JavaScript?

Edit
Report

3 Answers

64

So, after all it turned out, rounding bugs will always haunt you, no matter how hard you try to compensate them. Hence the problem should be attacked by representing numbers exactly in decimal notation.

Number.prototype.toFixedDown = function(digits) {
    var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
        m = this.toString().match(re);
    return m ? parseFloat(m[1]) : this.valueOf();
};

[   5.467.toFixedDown(2),
    985.943.toFixedDown(2),
    17.56.toFixedDown(2),
    (0).toFixedDown(1),
    1.11.toFixedDown(1) + 22];

// [5.46, 985.94, 17.56, 0, 23.1]

Old error-prone solution based on compilation of others':

Number.prototype.toFixedDown = function(digits) {
  var n = this - Math.pow(10, -digits)/2;
  n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56"
  return n.toFixed(digits);
}
answered 2011-02-06T11:01:46.597
21

Consider taking advantage of the double tilde: ~~.

Take in the number. Multiply by significant digits after the decimal so that you can truncate to zero places with ~~. Divide that multiplier back out. Profit.

function truncator(numToTruncate, intDecimalPlaces) {
    var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
    return ~~(numToTruncate * numPower)/numPower;
}

I'm trying to resist wrapping the ~~ call in parentheses; order of operations should make that work correctly, I believe.

alert(truncator(5.1231231, 1)); // is 5.1

alert(truncator(-5.73, 1)); // is -5.7

alert(truncator(-5.73, 0)); // is -5

JSFiddle link.

I've unintentionally also handled cases to round off left of the decimal as well.

alert(truncator(4343.123, -2)); // gives 4300.

The logic's a little wacky looking for that usage, and may benefit from a quick refactor. But it still works. Better lucky than good.

answered 2013-05-22T16:20:10.817
2

Here is my take on the subject:

convert.truncate = function(value, decimals) {
  decimals = (decimals === undefined ? 0 : decimals);
  return parseFloat((value-(0.5/Math.pow(10, decimals))).toFixed(decimals),10);
};

It's just a slightly more elaborate version of

(f - 0.005).toFixed(2)
answered 2013-05-15T06:04:28.137

Your Answer