Display two decimal places, no rounding

0 votes
asked Nov 15, 2010 by tempid

Suppose I have a value of 15.7784514, I want to display it 15.77 with no rounding.

var num = parseFloat(15.7784514);
document.write(num.toFixed(1)+"<br />");
document.write(num.toFixed(2)+"<br />");
document.write(num.toFixed(3)+"<br />");
document.write(num.toFixed(10));

Results in -

15.8
15.78
15.778
15.7784514000 

How do I display 15.77?

16 Answers

0 votes
answered Jan 15, 2010 by maerics

You could get the value to N decimal places of accuracy (use more for better effect) then drop the last unwanted characters of its string value:

var num = parseFloat(15.7784514);
var str = num.toFixed(10);
str = str.substring(0, str.length-7);
// str = 15.77
0 votes
answered Nov 15, 2010 by gumbo

Convert the number into a string, match the number up to the second decimal place:

var with2Decimals = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)[0]

The toFixed method fails in some cases unlike toString, so be very careful with it.

0 votes
answered Jan 5, 2012 by guya

Update 5 Nov 2016

New answer, always accurate

function toFixed(num, fixed) {
    var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
    return num.toString().match(re)[0];
}

As floating point math in javascript will always have edge cases, the previous solution will be accurate most of the time which is not good enough. There are some solutions to this like num.toPrecision, BigDecimal.js, and accounting.js. Yet, I believe that merely parsing the string will be the simplest and always accurate.

Basing the update on the well written regex from the accepted answer by @Gumbo, this new toFixed function will always work as expected.


Old answer, not always accurate.

Roll your own toFixed function:

function toFixed(num, fixed) {
    fixed = fixed || 0;
    fixed = Math.pow(10, fixed);
    return Math.floor(num * fixed) / fixed;
}
0 votes
answered Jan 7, 2013 by martin-varmus

parseInt is faster then Math.floor

function floorFigure(figure, decimals){
    if (!decimals) decimals = 2;
    var d = Math.pow(10,decimals);
    return (parseInt(figure*d)/d).toFixed(decimals);
};

floorFigure(123.5999)    =>   "123.59"
floorFigure(123.5999, 3) =>   "123.599"
0 votes
answered Jan 14, 2013 by jtrick

These solutions do work, but to me seem unnecessarily complicated. I personally like to use the modulus operator to obtain the remainder of a division operation, and remove that. Assuming that num = 15.7784514:

num-=num%.01;

This is equivalent to saying num = num - (num % .01).

0 votes
answered Jan 25, 2013 by jakir-hosen-khan

Thanks Martin Varmus

function floorFigure(figure, decimals){
     if (!decimals) decimals = 2;
     var d = Math.pow(10,decimals);
     return ((figure*d)/d).toFixed(decimals);
};

floorFigure(123.5999)    =>   "123.59"
floorFigure(123.5999, 3) =>   "123.599"

I make a simple update and I got proper rounding. The update is following line

return ((figure*d)/d).toFixed(decimals);

remove parseInt() function

0 votes
answered Jan 28, 2013 by boopathi-sakthivel

Roll your own toFixed function: for positive values Math.floor works fine.

function toFixed(num, fixed) {
    fixed = fixed || 0;
    fixed = Math.pow(10, fixed);
    return Math.floor(num * fixed) / fixed;
}

For negative values Math.floor is round of the values. So you can use Math.ceil instead.

Example,

Math.ceil(-15.778665 * 10000) / 10000 = -15.7786
Math.floor(-15.778665 * 10000) / 10000 = -15.7787 // wrong.
0 votes
answered Jan 17, 2014 by david-d

The answers here didn't help me, it kept rounding up or giving me the wrong decimal.

my solution converts your decimal to a string, extracts the characters and then returns the whole thing as a number.

function Dec2(num) {
  num = String(num);
  if(num.indexOf('.') !== -1) {
    var numarr = num.split(".");
    if (numarr.length == 1) {
      return Number(num);
    }
    else {
      return Number(numarr[0]+"."+numarr[1].charAt(0)+numarr[1].charAt(1));
    }
  }
  else {
    return Number(num);
  }  
}

Dec2(99); // 99
Dec2(99.9999999); // 99.99
Dec2(99.35154); // 99.35
Dec2(99.8); // 99.8
Dec2(10265.985475); // 10265.98
0 votes
answered Jan 13, 2015 by jakub-barczyk

Here you are. An answer that shows yet another way to solve the problem:

// Step-by-step demo of truncating a number to, say, 2 decimals:
var x = 0.1258, y = 0, z = 0; // we declare quite a few variables

y = x.toFixed(3); // we pass a number of decimals we want to keep +1

z = +(y.slice(0, --y.length)); // we assign final result to z

Note the use of + before final instruction. That is to convert our truncated, sliced string back to number type.

// For the sake of simplicity, here is a complete function:
function truncate(numberToBeTruncated, numberOfDecimalsToKeep) {
    var theNumber = (+numberToBeTruncated).toFixed(++numberOfDecimalsToKeep);
    return +(theNumber.slice(0, --theNumber.length));
};

Hope it helps!

0 votes
answered Jan 11, 2016 by daniel-barbalace

Gumbo's second solution, with the regular expression, does work but is slow because of the regular expression. Gumbo's first solution fails in certain situations due to imprecision in floating points numbers. See the JSFiddle for a demonstration and a benchmark. The second solution takes about 1636 nanoseconds per call on my current system, Intel Core i5-2500 CPU at 3.30 GHz.

The solution I've written involves adding a small compensation to take care of floating point imprecision. It is basically instantaneous, i.e. on the order of nanoseconds. I clocked 2 nanoseconds per call but the JavaScript timers are not very precise or granular. Here is the JS Fiddle and the code.

function toFixedWithoutRounding (value, precision)
{
    var factorError = Math.pow(10, 14);
    var factorTruncate = Math.pow(10, 14 - precision);
    var factorDecimal = Math.pow(10, precision);
    return Math.floor(Math.floor(value * factorError + 1) / factorTruncate) / factorDecimal;
}

var values = [1.1299999999, 1.13, 1.139999999, 1.14, 1.14000000001, 1.13 * 100];

for (var i = 0; i < values.length; i++)
{
    var value = values[i];
    console.log(value + " --> " + toFixedWithoutRounding(value, 2));
}

for (var i = 0; i < values.length; i++)
{
    var value = values[i];
    console.log(value + " --> " + toFixedWithoutRounding(value, 4));
}

console.log("type of result is " + typeof toFixedWithoutRounding(1.13 * 100 / 100, 2));

// Benchmark
var value = 1.13 * 100;
var startTime = new Date();
var numRun = 1000000;
var nanosecondsPerMilliseconds = 1000000;

for (var run = 0; run < numRun; run++)
    toFixedWithoutRounding(value, 2);

var endTime = new Date();
var timeDiffNs = nanosecondsPerMilliseconds * (endTime - startTime);
var timePerCallNs = timeDiffNs / numRun;
console.log("Time per call (nanoseconds): " + timePerCallNs);
Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...