Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript correctly rounding up to two decimals, impossible?

In php, we have number_format(). Passing it a value such as:

number_format(3.00 * 0.175, 2);

returns 0.53, which is what I would expect.

However, in JavaScript using toFixed()

var num = 3.00 * 0.175;
num.toFixed(2);

returns 0.52.

Ok, so perhaps toFixed is not what I want... Maybe something like this...

var num = 3.17 * 0.175;
var dec = 2;
Math.round( Math.round( num * Math.pow( 10, dec + 1 ) ) / Math.pow( 10, 1 ) ) / Math.pow(10,dec);

No, that doesn't work either. It will return 0.56.

How can I get a number_format function in JavaScript that doesn't give an incorrect answer?

Actually I did find an implementation of number_format for js, http://phpjs.org/functions/number_format, but it suffers from the same problem.

What is going on here with JavaScript rounding up? What am I missing?

like image 504
Bob Avatar asked Jun 21 '10 01:06

Bob


2 Answers

JavaScript does badly with floating point numbers (as do many other languages).

When I run

3.000 * 0.175

In my browser, I get

0.5249999999999999

Which will not round up to 0.525 with Math.round. To circumvent this, you kind of have to multiply both sides until you get them to be integers (relatively easy, knowing some tricks help though).

So to do this we can say something like this:

function money_multiply (a, b) {
    var log_10 = function (c) { return Math.log(c) / Math.log(10); },
        ten_e  = function (d) { return Math.pow(10, d); },
        pow_10 = -Math.floor(Math.min(log_10(a), log_10(b))) + 1;
    return ((a * ten_e(pow_10)) * (b * ten_e(pow_10))) / ten_e(pow_10 * 2);
}

This may look kind of funky, but here's some pseudo-code:

get the lowest power of 10 of the arguments (with log(base 10))
add 1 to make positive powers of ten (covert to integers)
multiply
divide by conversion factor (to get original quantities)

Hope this is what you are looking for. Here's a sample run:

3.000 * 0.175
0.5249999999999999

money_multiply(3.000, 0.175);
0.525
like image 74
Dan Beam Avatar answered Oct 05 '22 19:10

Dan Beam


The toFixed function is working correctly. It truncates past the specified amount of fraction digits.

like image 20
ChaosPandion Avatar answered Oct 05 '22 19:10

ChaosPandion