Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to round to at most 2 decimal places, if necessary?

I'd like to round at most 2 decimal places, but only if necessary.

Input:

10 1.7777777 9.1 

Output:

10 1.78 9.1 

How can I do this in JavaScript?

like image 346
stinkycheeseman Avatar asked Aug 06 '12 17:08

stinkycheeseman


2 Answers

Use Math.round() :

Math.round(num * 100) / 100 

Or to be more specific and to ensure things like 1.005 round correctly, use Number.EPSILON :

Math.round((num + Number.EPSILON) * 100) / 100 
like image 66
Brian Ustas Avatar answered Oct 20 '22 18:10

Brian Ustas


If the value is a text type:

parseFloat("123.456").toFixed(2); 

If the value is a number:

var numb = 123.23454; numb = numb.toFixed(2); 

There is a downside that values like 1.5 will give "1.50" as the output. A fix suggested by @minitech:

var numb = 1.5; numb = +numb.toFixed(2); // Note the plus sign that drops any "extra" zeroes at the end. // It changes the result (which is a string) into a number again (think "0 + foo"), // which means that it uses only as many digits as necessary. 

It seems like Math.round is a better solution. But it is not! In some cases it will NOT round correctly:

Math.round(1.005 * 100)/100 // Returns 1 instead of expected 1.01! 

toFixed() will also NOT round correctly in some cases (tested in Chrome v.55.0.2883.87)!

Examples:

parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56. parseFloat("1.5550").toFixed(2); // Returns 1.55 instead of 1.56. // However, it will return correct result if you round 1.5551. parseFloat("1.5551").toFixed(2); // Returns 1.56 as expected.  1.3555.toFixed(3) // Returns 1.355 instead of expected 1.356. // However, it will return correct result if you round 1.35551. 1.35551.toFixed(2); // Returns 1.36 as expected. 

I guess, this is because 1.555 is actually something like float 1.55499994 behind the scenes.

Solution 1 is to use a script with required rounding algorithm, for example:

function roundNumber(num, scale) {   if(!("" + num).includes("e")) {     return +(Math.round(num + "e+" + scale)  + "e-" + scale);   } else {     var arr = ("" + num).split("e");     var sig = ""     if(+arr[1] + scale > 0) {       sig = "+";     }     return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);   } } 

https://plnkr.co/edit/uau8BlS1cqbvWPCHJeOy?p=preview

NOTE: This is not a universal solution for everyone. There are several different rounding algorithms, your implementation can be different, depends on your requirements. https://en.wikipedia.org/wiki/Rounding

Solution 2 is to avoid front end calculations and pull rounded values from the backend server.

Edit: Another possible solution, which is not a bullet proof also.

Math.round((num + Number.EPSILON) * 100) / 100 

In some cases, when you round number like 1.3549999999999998 it will return incorrect result. Should be 1.35 but result is 1.36.

like image 45
A Kunin Avatar answered Oct 20 '22 17:10

A Kunin