Javascript: formatting a rounded number to N decimals

173,207

Solution 1

That's not a rounding ploblem, that is a display problem. A number doesn't contain information about significant digits; the value 2 is the same as 2.0000000000000. It's when you turn the rounded value into a string that you have make it display a certain number of digits.

You could just add zeroes after the number, something like:

var s = number.toString();
if (s.indexOf('.') == -1) s += '.';
while (s.length < s.indexOf('.') + 4) s += '0';

(Note that this assumes that the regional settings of the client uses period as decimal separator, the code needs some more work to function for other settings.)

Solution 2

I think that there is a more simple approach to all given here, and is the method Number.toFixed() already implemented in JavaScript.

simply write:

var myNumber = 2;

myNumber.toFixed(2); //returns "2.00"
myNumber.toFixed(1); //returns "2.0"

etc...

Solution 3

I found a way. This is Christoph's code with a fix:

function toFixed(value, precision) {
    var precision = precision || 0,
        power = Math.pow(10, precision),
        absValue = Math.abs(Math.round(value * power)),
        result = (value < 0 ? '-' : '') + String(Math.floor(absValue / power));

    if (precision > 0) {
        var fraction = String(absValue % power),
            padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');
        result += '.' + padding + fraction;
    }
    return result;
}

Read the details of repeating a character using an array constructor here if you are curious as to why I added the "+ 1".

Solution 4

There's always a better way for doing things. Use toPrecision -

var number = 51.93999999999761;

I would like to get four digits precision: 51.94

just do:

number.toPrecision(4);

the result will be: 51.94

Solution 5

PHP-Like rounding Method

The code below can be used to add your own version of Math.round to your own namespace which takes a precision parameter. Unlike Decimal rounding in the example above, this performs no conversion to and from strings, and the precision parameter works same way as PHP and Excel whereby a positive 1 would round to 1 decimal place and -1 would round to the tens.

var myNamespace = {};
myNamespace.round = function(number, precision) {
    var factor = Math.pow(10, precision);
    var tempNumber = number * factor;
    var roundedTempNumber = Math.round(tempNumber);
    return roundedTempNumber / factor;
};

myNamespace.round(1234.5678, 1); // 1234.6
myNamespace.round(1234.5678, -1); // 1230

from Mozilla Developer reference for Math.round()

Share:
173,207

Related videos on Youtube

hoju
Author by

hoju

nothing to see here, move along now

Updated on July 08, 2022

Comments

  • hoju
    hoju almost 2 years

    in JavaScript, the typical way to round a number to N decimal places is something like:

    function roundNumber(num, dec) {
      return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
    }
    

    function roundNumber(num, dec) {
      return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
    }
    
    console.log(roundNumber(0.1 + 0.2, 2));
    console.log(roundNumber(2.1234, 2));

    However this approach will round to a maximum of N decimal places while I want to always round to N decimal places. For example "2.0" would be rounded to "2".

    Any ideas?

  • Elias Zamaria
    Elias Zamaria almost 14 years
    Your code has a bug. I tried toFixed(2.01, 4) and got a result of "2.100". If I ever find a way to fix it, I will post it as an answer to this question.
  • Christoph
    Christoph almost 14 years
    @mikez302: the padding computation was off by one; should work now, but feel free to bug me again if it's still broken...
  • Bat_Programmer
    Bat_Programmer over 12 years
    toFixed is buggy..for instance the decimal: 1.02449999998 if u do dec.toFixed(4) => 1.0244. It should have been 1.0245 instead.
  • pauloya
    pauloya over 12 years
    @deepeshk But what would be the problem with using toFixed() to pad decimals at the end, after rounding?
  • Matt Ball
    Matt Ball about 12 years
    @deepeshk in what browser? Just tried it in Chrome 17 and 1.02449999998.toFixed(4) correctly returns 1.0245.
  • Rick Kukiela
    Rick Kukiela over 11 years
    Very strange. When I run this fuction with the firebug console open in firefox 17 it freezes the whole browser like js is caught in an endless loop. Even if i do not console.log the output. If I do not have firebug activated the bug does not occur.
  • Rick Kukiela
    Rick Kukiela over 11 years
    Update, i ran it in chrome and i get: Uncaught RangeError: Maximum call stack size exceeded in regards to the toFixed function call.
  • Christoph
    Christoph over 11 years
    @SublymeRick: I have no idea why this happens; shot in the dark: try renaming the function...
  • Mark Tomlin
    Mark Tomlin almost 11 years
    @Mark got most of the answer, but after some research you need to call it like this, Number(float).toFxied(places);.
  • Guffa
    Guffa almost 11 years
    @MarkTomlin: Then it seems that you have a string instead of a number.
  • Mark Tomlin
    Mark Tomlin almost 11 years
    @Guffa thanks' for the clarification, I'm kinda fumbling my way through JavaScript programming right now. +1.
  • alan
    alan over 10 years
    Passing in a value of 708.3333333333333 with a precision of 2 or 3 results in a return value of 708.00 for me. I need this for 2 decimal places, in Chrome and IE 9 .toFixed(2) met my needs.
  • alan
    alan over 10 years
    As an FYI, if you only need precision to 2 decimal places .toFixed works for both IE and Chrome.
  • David
    David about 10 years
    Where is mentioned, hoju? I reviewed other answers and I didn't find anyone reporting that toFixed function is buggy. Thanks
  • hiway
    hiway almost 10 years
    this is not a common way, e.g, toFixed(16.775, 2) return 16.77. Convert number to String then convert is the only way.
  • Matt
    Matt over 9 years
    There is a bug with this method: toFixed(-0.1111, 2) returns 0.11, i.e. the negative sign is lost.
  • Elias Zamaria
    Elias Zamaria over 9 years
    I tried format(1.2, 5) and got 1.2, while I expected 1.20000.
  • Artur Barseghyan
    Artur Barseghyan about 9 years
    Works great, except for that I have added parseFloat(result) at the end. Worth an edit.
  • robocat
    robocat almost 9 years
    .toFixed() works brilliantly in modern browsers (I tested Chrome, Firefox, IE11, IE8). @Bat_Programmer - please clarify which browsers you think have that bug.
  • Guffa
    Guffa almost 9 years
  • robocat
    robocat almost 9 years
    .toFixed() is fixed in IE8+ (my testing) but apparently buggy in IE7 (as per @Guffa link in comment above - thank you). So use toFixed() unless you need to support IE7 ;-)
  • robocat
    robocat almost 9 years
    Do NOT USE this answer because it has serious bugs: it gives incorrect answers: NaN -> NaN.000, Infinity -> Infinity.000, 9e60 -> 9E60.000, 0.000001 -> 0.000001 (0.000001.toFixed(3) correctly gives 0.000).
  • Guffa
    Guffa almost 9 years
    @robocat: Are you serious?
  • robocat
    robocat almost 9 years
    @Guffa - .toFixed() works correctly in IE8+. e.g. I just run IE8 using the example from the link of (0.595).toFixed(2) and got correct answer of 0.60. Your code is broken for corner cases (the few I thought of from the top of my head with a few minutes testing, I could probably find other things wrong with it), and is not suitable for production code IMHO.
  • Guffa
    Guffa almost 9 years
    @robocat: You are looking for something that I never claimed that the code would be. Besdies, you can just as easily find corner cases where toFixed is broken, for example (1000000000000000000000).toFixed(3) returns 1e+21 not 1000000000000000000000.000.
  • Guffa
    Guffa almost 9 years
    @David: That's mentioned in a comment to the answer, for example.
  • Juan Carrey
    Juan Carrey almost 9 years
    Sorry @EliasZamaria , didn't understand it at first. I have edited the post. Just note that it wil return "0.0000" when value is undefined.
  • Jordan Arseno
    Jordan Arseno over 8 years
    caution: toFixed() returns a string.
  • JohnnyBizzle
    JohnnyBizzle over 7 years
    And what if you add 100? Do you need to change it to number.toPrecision(5)?
  • ReSpawN
    ReSpawN over 7 years
    Yes. 31.939383.toPrecision(4) > "31.94" / 131.939383.toPrecision(4) > "131.9"
  • AaA
    AaA over 6 years
    @Christoph, I believe it is happening because of stacking all vars and calculations with comma on a single var statement. It breaks the debugger, but works in browser.I had similar case with a larger script, if I remember correctly on Firefox 42
  • Stephen Romero
    Stephen Romero over 5 years
    @JordanArseno this can be fixed using parseInt(myNumber.toFixed(intVar)); to return an integer value, or parseFloat(myNumber.toFixed(floatVar)); to return a float if user has decimal places.
  • George Birbilis
    George Birbilis over 4 years
    btw, POSITS are promising for future h/w architectures: nextplatform.com/2019/07/08/…