Reputation: 33
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
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
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
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
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