user1778939
user1778939

Reputation: 33

Rounding numbers in javascript

what is the best way to round commercial in javasript?

Example:

0.145 -> ToString(2) -> 0.14

mathjs:
math.round(0.145, 2)) -> 0.14

also math pow with round won´t work 100%

At the Moment i use:

function number_format(number, decimals, dec_point, thousands_sep) {
    number = number + 0.000000001;
    number = (number + '').replace(/[^0-9+\-Ee.]/g, '');

    var n    = !isFinite(+number)   ? 0 : +number,
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
        sep  = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec  = (typeof dec_point     === 'undefined') ? '.' : dec_point,
        s    = '',
        toFixedFix = function(n, prec) {
                         var k = Math.pow(10, prec);
                         return '' + Math.round(n * k) / k;
                     };

   // Fix for IE parseFloat(0.55).toFixed(0) = 0;
   s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');

   if (s[0].length > 3) 
   {
      s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
   }

   if ((s[1] || '').length < prec) {
     s[1]  = s[1] || '';
     s[1] += new Array(prec - s[1].length + 1).join('0');
   }

   return s.join(dec);
}

With this fix ( number = number + 0.000000001;) i get 0.15

Is there a better way to do it?

Upvotes: 0

Views: 1266

Answers (4)

Christophe Roussy
Christophe Roussy

Reputation: 16999

Out of curiosity here is a technique dealing with integer division and even rounding is the technique discussed by Daniel Lemire and Falk Hüffner:

function roundToEven(n, d) {
  var off = (n + d / 2)
  var roundup = off / d;
  var ismultiple = ((off % d) == 0);
  return (d | (roundup ^ ismultiple)) & roundup;
}

Math.round(3/2);
2
roundToEven(3,2);
2

You may be concerned with overflows. Indeed, if both n and d are large, it is possible for n+d/2 to exceed to allowable range.

Upvotes: 0

RobG
RobG

Reputation: 147343

The rounding you mention is also called "banker's rounding", where if a number is to be rounded to n digits, then if the n+1 digit is 5 the nth digit is rounded to the nearest even number,

e.g. rounding to 2 places:

2.345 => 2.34
2.335 => 2.34

The following may suit, it's not thoroughly tested and has limits on the size of numbers that can be rounded, but it shows an approach. It's based on toFixed so returns a string.

function bankersRound(n, d) {
    var a, b;
    var p = String(n).split('.');

    if (p[1]) {
      a = p[1].substr(0, d);
      b = p[1].substr(d, 1);

      // If the d+1 character is 5 and the d character is even, force
      // toFixed to round down
      if (b == 5 && !(a%2)) {
          n = p[0] + '.' + a + '4';
      }
    }
    return Number(n).toFixed(d);
}

console.log(bankersRound(23.365, 2)); // 23.36
console.log(bankersRound(23.366, 2)); // 23.37
console.log(bankersRound(23.355, 2)); // 23.36
console.log(bankersRound(23.345, 2)); // 23.34
console.log(bankersRound(23.335, 2)); // 23.34

Upvotes: 1

Theofilos Mouratidis
Theofilos Mouratidis

Reputation: 1156

Math.round() will do the job for you in integers. You can do a nice approach by multiplying your number by a power of 10, then round, then divide by the same number.

@Example: Decimal rounding
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round

and a benchmark between them.

http://jsperf.com/roundingnumbers2

So my approach is faster than the others :), but not very safe for really big numbers

Upvotes: 0

Tomalak
Tomalak

Reputation: 338108

If it is purely about formatting a currency value you can use a dedicated library like accounting.js.

accounting.toFixed(0.615, 2); // "0.62"

accounting.formatMoney(12345678); // $12,345,678.00

accounting.formatMoney(4999.99, "€", 2, ".", ","); // €4.999,99

Upvotes: 0

Related Questions