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?

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?

javascript
decimal
rounding
decimal-point
121
0
stinkycheeseman
2020-03-17 12:30:30 +0000 UTC

Use `Math.round(num * 100) / 100`

**Edit:** to ensure things like 1.005 round correctly, we use

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

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 * 1000)/1000 // 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.

MarkG's answer is the correct one. Here's a generic extension for any number of decimal places.

```
Number.prototype.round = function(places) {
return +(Math.round(this + "e+" + places) + "e-" + places);
}
```

Usage:

```
var n = 1.7777;
n.round(2); // 1.78
```

Unit test:

```
it.only('should round floats to 2 places', function() {
var cases = [
{ n: 10, e: 10, p:2 },
{ n: 1.7777, e: 1.78, p:2 },
{ n: 1.005, e: 1.01, p:2 },
{ n: 1.005, e: 1, p:0 },
{ n: 1.77777, e: 1.8, p:1 }
]
cases.forEach(function(testCase) {
var r = testCase.n.round(testCase.p);
assert.equal(r, testCase.e, 'didn\'t get right number');
});
})
```

You should use:

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

No one seems to be aware of `Number.EPSILON`

.

Also it's worth noting that this is not a *JavaScript weirdness* like some people stated.

**That is simply the way floating point numbers works in a computer.** Like 99% of programming languages, JavaScript doesn't have *home made* floating point numbers; it relies on the CPU/FPU for that. A computer uses binary, and in binary, there isn't any numbers like `0.1`

, but a mere binary approximation for that. Why? For the same reason than 1/3 cannot be written in decimal: its value is 0.33333333... with an infinity of threes.

Here come `Number.EPSILON`

. That number is the difference between 1 and the *next* number existing in the double precision floating point numbers. **That's it: There is no number between 1 and 1 + Number.EPSILON.**

**EDIT:**

As asked in the comments, let's clarify one thing: adding `Number.EPSILON`

is relevant only when the value to round is the result of an arithmetic operation, as it can swallow some floating point error delta.

It's not useful when the value comes from a direct source (e.g.: literal, user input or sensor).

**EDIT (2019):**

Like @maganap and some peoples have pointed out, it's best to add `Number.EPSILON`

before multiplying:

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

**EDIT (december 2019):**

Lately, I use a function similar to this one for comparing numbers epsilon-aware:

```
const ESPILON_RATE = 1 + Number.EPSILON ;
const ESPILON_ZERO = Number.MIN_VALUE ;
function epsilonEquals( a , b ) {
if ( Number.isNaN( a ) || Number.isNaN( b ) ) {
return false ;
}
if ( a === 0 || b === 0 ) {
return a <= b + EPSILON_ZERO && b <= a + EPSILON_ZERO ;
}
return a <= b * EPSILON_RATE && b <= a * EPSILON_RATE ;
}
```

My use-case is an assertion + data validation lib I'm developing for many years.

In fact, in the code I'm using `ESPILON_RATE = 1 + 4 * Number.EPSILON`

and `EPSILON_ZERO = 4 * Number.MIN_VALUE`

(four times the epsilon), because I want an equality checker loose enough for cumulating floating point error.

So far, it looks perfect for me. I hope it will help.

One can use `.toFixed(NumberOfDecimalPlaces)`

.

```
var str = 10.234.toFixed(2); // => '10.23'
var number = Number(str); // => 10.23
```

Consider `.toFixed()`

and `.toPrecision()`

:

This question is complicated.

Suppose we have a function, `roundTo2DP(num)`

, that takes a float as an argument and returns a value rounded to 2 decimal places. What should each of these expressions evaluate to?

`roundTo2DP(0.014999999999999999)`

`roundTo2DP(0.0150000000000000001)`

`roundTo2DP(0.015)`

The 'obvious' answer is that the first example should round to 0.01 (because it's closer to 0.01 than to 0.02) while the other two should round to 0.02 (because 0.0150000000000000001 is closer to 0.02 than to 0.01, and because 0.015 is exactly halfway between them and there is a mathematical convention that such numbers get rounded up).

The catch, which you may have guessed, is that `roundTo2DP`

*cannot possibly* be implemented to give those obvious answers, because all three numbers passed to it are *the same number*. IEEE 754 binary floating point numbers (the kind used by JavaScript) can't exactly represent most non-integer numbers, and so all three numeric literals above get rounded to a nearby valid floating point number. This number, as it happens, is *exactly*

0.01499999999999999944488848768742172978818416595458984375

which is closer to 0.01 than to 0.02.

You can see that all three numbers are the same at your browser console, Node shell, or other JavaScript interpreter. Just compare them:

`> `*0.014999999999999999 === 0.0150000000000000001*
true

So when I write `m = 0.0150000000000000001`

, the *exact value of m* that I end up with is closer to

`0.01`

than it is to `0.02`

. And yet, if I convert `m`

to a String...`> `*var m = 0.0150000000000000001;*
> *console.log(String(m));*
0.015
> *var m = 0.014999999999999999;*
> *console.log(String(m));*
0.015

... I get 0.015, which should round to 0.02, and which is noticeably *not* the 56-decimal-place number I earlier said that all of these numbers were exactly equal to. So what dark magic is this?

The answer can be found in the ECMAScript specification, in section *7.1.12.1: ToString applied to the Number type*. Here the rules for converting some Number *m* to a String are laid down. The key part is point 5, in which an integer *s* is generated whose digits will be used in the String representation of *m*:

let

n,k, andsbe integers such thatk? 1, 10^{k-1}?s< 10^{k}, the Number value fors× 10^{n-k}ism, andkis as small as possible. Note that k is the number of digits in the decimal representation ofs, thatsis not divisible by 10, and that the least significant digit ofsis not necessarily uniquely determined by these criteria.

The key part here is the requirement that "*k* is as small as possible". What that requirement amounts to is a requirement that, given a Number `m`

, the value of `String(m)`

must have *the least possible number of digits* while still satisfying the requirement that `Number(String(m)) === m`

. Since we already know that `0.015 === 0.0150000000000000001`

, it's now clear why `String(0.0150000000000000001) === '0.015'`

must be true.

Of course, none of this discussion has directly answered what `roundTo2DP(m)`

*should* return. If `m`

's exact value is 0.01499999999999999944488848768742172978818416595458984375, but its String representation is '0.015', then what is the *correct* answer - mathematically, practically, philosophically, or whatever - when we round it to two decimal places?

There is no single correct answer to this. It depends upon your use case. You probably want to respect the String representation and round upwards when:

- The value being represented is inherently discrete, e.g. an amount of currency in a 3-decimal-place currency like dinars. In this case, the
*true*value of a Number like 0.015*is*0.015, and the 0.0149999999... representation that it gets in binary floating point is a rounding error. (Of course, many will argue, reasonably, that you should use a decimal library for handling such values and never represent them as binary floating point Numbers in the first place.) - The value was typed by a user. In this case, again, the exact decimal number entered is more 'true' than the nearest binary floating point representation.

On the other hand, you probably want to respect the binary floating point value and round downwards when your value is from an inherently continuous scale - for instance, if it's a reading from a sensor.

These two approaches require different code. To respect the String representation of the Number, we can (with quite a bit of reasonably subtle code) implement our own rounding that acts directly on the String representation, digit by digit, using the same algorithm you would've used in school when you were taught how to round numbers. Below is an example which respects the OP's requirement of representing the number to 2 decimal places "only when necessary" by stripping trailing zeroes after the decimal point; you may, of course, need to tweak it to your precise needs.

```
/**
* Converts num to a decimal string (if it isn't one already) and then rounds it
* to at most dp decimal places.
*
* For explanation of why you'd want to perform rounding operations on a String
* rather than a Number, see http://stackoverflow.com/a/38676273/1709587
*
* @param {(number|string)} num
* @param {number} dp
* @return {string}
*/
function roundStringNumberWithoutTrailingZeroes (num, dp) {
if (arguments.length != 2) throw new Error("2 arguments required");
num = String(num);
if (num.indexOf('e+') != -1) {
// Can't round numbers this large because their string representation
// contains an exponent, like 9.99e+37
throw new Error("num too large");
}
if (num.indexOf('.') == -1) {
// Nothing to do
return num;
}
var parts = num.split('.'),
beforePoint = parts[0],
afterPoint = parts[1],
shouldRoundUp = afterPoint[dp] >= 5,
finalNumber;
afterPoint = afterPoint.slice(0, dp);
if (!shouldRoundUp) {
finalNumber = beforePoint + '.' + afterPoint;
} else if (/^9+$/.test(afterPoint)) {
// If we need to round up a number like 1.9999, increment the integer
// before the decimal point and discard the fractional part.
finalNumber = Number(beforePoint)+1;
} else {
// Starting from the last digit, increment digits until we find one
// that is not 9, then stop
var i = dp-1;
while (true) {
if (afterPoint[i] == '9') {
afterPoint = afterPoint.substr(0, i) +
'0' +
afterPoint.substr(i+1);
i--;
} else {
afterPoint = afterPoint.substr(0, i) +
(Number(afterPoint[i]) + 1) +
afterPoint.substr(i+1);
break;
}
}
finalNumber = beforePoint + '.' + afterPoint;
}
// Remove trailing zeroes from fractional part before returning
return finalNumber.replace(/0+$/, '')
}
```

Example usage:

`> `*roundStringNumberWithoutTrailingZeroes(1.6, 2)*
'1.6'
> *roundStringNumberWithoutTrailingZeroes(10000, 2)*
'10000'
> *roundStringNumberWithoutTrailingZeroes(0.015, 2)*
'0.02'
> *roundStringNumberWithoutTrailingZeroes('0.015000', 2)*
'0.02'
> *roundStringNumberWithoutTrailingZeroes(1, 1)*
'1'
> *roundStringNumberWithoutTrailingZeroes('0.015', 2)*
'0.02'
> *roundStringNumberWithoutTrailingZeroes(0.01499999999999999944488848768742172978818416595458984375, 2)*
'0.02'
> *roundStringNumberWithoutTrailingZeroes('0.01499999999999999944488848768742172978818416595458984375', 2)*
'0.01'

The function above is *probably* what you want to use to avoid users ever witnessing numbers that they have entered being rounded wrongly.

(As an alternative, you could also try the round10 library which provides a similarly-behaving function with a wildly different implementation.)

But what if you have the second kind of Number - a value taken from a continuous scale, where there's no reason to think that approximate decimal representations with fewer decimal places are more *accurate* than those with more? In that case, we *don't* want to respect the String representation, because that representation (as explained in the spec) is already sort-of-rounded; we don't want to make the mistake of saying "0.014999999...375 rounds up to 0.015, which rounds up to 0.02, so 0.014999999...375 rounds up to 0.02".

Here we can simply use the built-in `toFixed`

method. Note that by calling `Number()`

on the String returned by `toFixed`

, we get a Number whose String representation has no trailing zeroes (thanks to the way JavaScript computes the String representation of a Number, discussed earlier in this answer).

```
/**
* Takes a float and rounds it to at most dp decimal places. For example
*
* roundFloatNumberWithoutTrailingZeroes(1.2345, 3)
*
* returns 1.234
*
* Note that since this treats the value passed to it as a floating point
* number, it will have counterintuitive results in some cases. For instance,
*
* roundFloatNumberWithoutTrailingZeroes(0.015, 2)
*
* gives 0.01 where 0.02 might be expected. For an explanation of why, see
* http://stackoverflow.com/a/38676273/1709587. You may want to consider using the
* roundStringNumberWithoutTrailingZeroes function there instead.
*
* @param {number} num
* @param {number} dp
* @return {number}
*/
function roundFloatNumberWithoutTrailingZeroes (num, dp) {
var numToFixedDp = Number(num).toFixed(dp);
return Number(numToFixedDp);
}
```

A precise rounding method. Source: Mozilla

```
(function(){
/**
* Decimal adjustment of a number.
*
* @param {String} type The type of adjustment.
* @param {Number} value The number.
* @param {Integer} exp The exponent (the 10 logarithm of the adjustment base).
* @returns {Number} The adjusted value.
*/
function decimalAdjust(type, value, exp) {
// If the exp is undefined or zero...
if (typeof exp === 'undefined' || +exp === 0) {
return Math[type](value);
}
value = +value;
exp = +exp;
// If the value is not a number or the exp is not an integer...
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
return NaN;
}
// Shift
value = value.toString().split('e');
value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
// Shift back
value = value.toString().split('e');
return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
}
// Decimal round
if (!Math.round10) {
Math.round10 = function(value, exp) {
return decimalAdjust('round', value, exp);
};
}
// Decimal floor
if (!Math.floor10) {
Math.floor10 = function(value, exp) {
return decimalAdjust('floor', value, exp);
};
}
// Decimal ceil
if (!Math.ceil10) {
Math.ceil10 = function(value, exp) {
return decimalAdjust('ceil', value, exp);
};
}
})();
```

Examples:

```
// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50
```

**None of the answers found here is correct**. @stinkycheeseman asked to **round up**, you all rounded the number.

To round up, use this:

```
Math.ceil(num * 100)/100;
```

Here is a simple way to do it:

```
Math.round(value * 100) / 100
```

You might want to go ahead and make a separate function to do it for you though:

```
function roundToTwo(value) {
return(Math.round(value * 100) / 100);
}
```

Then you would simply pass in the value.

You could enhance it to round to any arbitrary number of decimals by adding a second parameter.

```
function myRound(value, places) {
var multiplier = Math.pow(10, places);
return (Math.round(value * multiplier) / multiplier);
}
```

```
+(10).toFixed(2); // = 10
+(10.12345).toFixed(2); // = 10.12
(10).toFixed(2); // = 10.00
(10.12345).toFixed(2); // = 10.12
```

For me Math.round() was not giving correct answer. I found toFixed(2) works better. Below are examples of both:

```
console.log(Math.round(43000 / 80000) * 100); // wrong answer
console.log(((43000 / 80000) * 100).toFixed(2)); // correct answer
```

Use this function `Number(x).toFixed(2);`

Try this **light weight** solution:

```
function round(x, digits){
return parseFloat(x.toFixed(digits))
}
round(1.222, 2) ;
// 1.22
round(1.222, 10) ;
// 1.222
```

2017

Just use native code `.toFixed()`

```
number = 1.2345;
number.toFixed(2) // "1.23"
```

If you need to be strict and add digits just if needed it can use `replace`

```
number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');
```

There are a couple of ways to do that. For people like me, the Lodash's variant

```
function round(number, precision) {
var pair = (number + 'e').split('e')
var value = Math.round(pair[0] + 'e' + (+pair[1] + precision))
pair = (value + 'e').split('e')
return +(pair[0] + 'e' + (+pair[1] - precision))
}
```

**Usage:**

```
round(0.015, 2) // 0.02
round(1.005, 2) // 1.01
```

If your project uses jQuery or lodash, you can also find proper `round`

method in the libraries.

I removed the variant `n.toFixed(2)`

, because it is not correct. Thank you @avalanche1

If you are using lodash library, you can use the round method of lodash like following.

```
_.round(number, precision)
```

Eg:

```
_.round(1.7777777, 2) = 1.78
```

Since ES6 there is a 'proper' way (without overriding statics and creating workarounds) to do this by using toPrecision

```
var x = 1.49999999999;
console.log(x.toPrecision(4));
console.log(x.toPrecision(3));
console.log(x.toPrecision(2));
var y = Math.PI;
console.log(y.toPrecision(6));
console.log(y.toPrecision(5));
console.log(y.toPrecision(4));
var z = 222.987654
console.log(z.toPrecision(6));
console.log(z.toPrecision(5));
console.log(z.toPrecision(4));
```

then you can just `parseFloat`

and zeroes will 'go away'.

```
console.log(parseFloat((1.4999).toPrecision(3)));
console.log(parseFloat((1.005).toPrecision(3)));
console.log(parseFloat((1.0051).toPrecision(3)));
```

It doesn't solve the '1.005 rounding problem' though - since it is intrinsic to how float fractions are being processed.

`console.log(1.005 - 0.005);`

If you are open to libraries you can use bignumber.js

```
console.log(1.005 - 0.005);
console.log(new BigNumber(1.005).minus(0.005));
console.log(new BigNumber(1.005).round(4));
console.log(new BigNumber(1.005).round(3));
console.log(new BigNumber(1.005).round(2));
console.log(new BigNumber(1.005).round(1));
```

`<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/2.3.0/bignumber.min.js"></script>`

MarkG and Lavamantis offered a much better solution than the one that has been accepted. It's a shame they don't get more upvotes!

Here is the function I use to solve the floating point decimals issues also based on MDN. It is even more generic (but less concise) than Lavamantis's solution:

```
function round(value, exp) {
if (typeof exp === 'undefined' || +exp === 0)
return Math.round(value);
value = +value;
exp = +exp;
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
return NaN;
// Shift
value = value.toString().split('e');
value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));
// Shift back
value = value.toString().split('e');
return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}
```

Use it with:

```
round(10.8034, 2); // Returns 10.8
round(1.275, 2); // Returns 1.28
round(1.27499, 2); // Returns 1.27
round(1.2345678e+2, 2); // Returns 123.46
```

Compared to Lavamantis's solution, we can do...

```
round(1234.5678, -2); // Returns 1200
round("123.45"); // Returns 123
```

This may help you:

```
var result = Math.round(input*100)/100;
```

for more information, you can have a look at this link

Math.round(num) vs num.toFixed(0) and browser inconsistencies

```
var roundUpto = function(number, upto){
return Number(number.toFixed(upto));
}
roundUpto(0.1464676, 2);
```

`toFixed(2)`

here 2 is number of digits upto which we want to round this num.

It may work for you,

```
Math.round(num * 100)/100;
```

to know the difference between toFixed and round. You can have a look at *Math.round(num) vs num.toFixed(0) and browser inconsistencies*.

Easiest way:

`+num.toFixed(2)`

It converts it to a string, and then back into an integer / float.

Here is a prototype method:

```
Number.prototype.round = function(places){
places = Math.pow(10, places);
return Math.round(this * places)/places;
}
var yournum = 10.55555;
yournum = yournum.round(2);
```

Use something like this "parseFloat(parseFloat(value).toFixed(2))"

```
parseFloat(parseFloat("1.7777777").toFixed(2))-->1.78
parseFloat(parseFloat("10").toFixed(2))-->10
parseFloat(parseFloat("9.1").toFixed(2))-->9.1
```

One way to achieve such a rounding *only if necessary* is to use Number.prototype.toLocaleString():

```
myNumber.toLocaleString('en', {maximumFractionDigits:2, useGrouping:false})
```

This will provide exactly the output you expect, but as strings. You can still convert those back to numbers if that's not the data type you expect.

In general, rounding is done by scaling: `round(num / p) * p`

Using the exponential notation handles rounding of +ve numbers, correctly. However, this method fails to round -ve edge cases correctly.

```
function round(num, precision = 2) {
var scaled = Math.round(num + "e" + precision);
return Number(scaled + "e" + -precision);
}
// testing some edge cases
console.log( round(1.005, 2) ); // 1.01 correct
console.log( round(2.175, 2) ); // 2.18 correct
console.log( round(5.015, 2) ); // 5.02 correct
console.log( round(-1.005, 2) ); // -1 wrong
console.log( round(-2.175, 2) ); // -2.17 wrong
console.log( round(-5.015, 2) ); // -5.01 wrong
```

Here, also is one function I wrote to do arithmetic rounding correctly. You can test it yourself.

```
/**
* MidpointRounding away from zero ('arithmetic' rounding)
* Uses a half-epsilon for correction. (This offsets IEEE-754
* half-to-even rounding that was applied at the edge cases).
*/
function RoundCorrect(num, precision = 2) {
// half epsilon to correct edge cases.
var c = 0.5 * Number.EPSILON * num;
// var p = Math.pow(10, precision); //slow
var p = 1; while (precision--> 0) p *= 10;
if (num < 0)
p *= -1;
return Math.round((num + c) * p) / p;
}
// testing some edge cases
console.log(RoundCorrect(1.005, 2)); // 1.01 correct
console.log(RoundCorrect(2.175, 2)); // 2.18 correct
console.log(RoundCorrect(5.015, 2)); // 5.02 correct
console.log(RoundCorrect(-1.005, 2)); // -1.01 correct
console.log(RoundCorrect(-2.175, 2)); // -2.18 correct
console.log(RoundCorrect(-5.015, 2)); // -5.02 correct
```

To not deal with many 0s, use this variant:

```
Math.round(num * 1e2) / 1e2
```

If you happen to already be using the d3 library, they have a powerful number formatting library: https://github.com/mbostock/d3/wiki/Formatting

Rounding specifically is here: https://github.com/mbostock/d3/wiki/Formatting#d3_round

In your case, the answer is:

```
> d3.round(1.777777, 2)
1.78
> d3.round(1.7, 2)
1.7
> d3.round(1, 2)
1
```

This is the simplest, more elegant solution (and I am the best of the world;):

```
function roundToX(num, X) {
return +(Math.round(num + "e+"+X) + "e-"+X);
}
//roundToX(66.66666666,2) => 66.67
//roundToX(10,2) => 10
//roundToX(10.904,2) => 10.9
```

After running through various iterations of all the possible ways to achieve true accurate decimal rounding precision, it is clear that the most accurate and efficient solution is to use Number.EPSILON. This provides a true mathematical solution to the problem of floating point math precision. It can be easily polyfilled as shown here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON to support all of the last remaining IE users (then again maybe we should stop doing that).

Adapted from the solution provided here: https://stackoverflow.com/a/48850944/6910392

A simple drop in solution that provides accurate decimal rounding, flooring, and ceiling, with an optional precision variable without adding a whole library.

```
var DecimalPrecision = (function(){
if (Number.EPSILON === undefined) {
Number.EPSILON = Math.pow(2, -52);
}
this.round = function(n, p=2){
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
if(n < 0)
o *= -1;
return Math.round((n + r) * o) / o;
}
this.ceil = function(n, p=2){
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
if(n < 0)
o *= -1;
return Math.ceil((n + r) * o) / o;
}
this.floor = function(n, p=2){
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
if(n < 0)
o *= -1;
return Math.floor((n + r) * o) / o;
}
return this;
})();
console.log(DecimalPrecision.round(1.005));
console.log(DecimalPrecision.ceil(1.005));
console.log(DecimalPrecision.floor(1.005));
console.log(DecimalPrecision.round(1.0049999));
console.log(DecimalPrecision.ceil(1.0049999));
console.log(DecimalPrecision.floor(1.0049999));
console.log(DecimalPrecision.round(2.175495134384,7));
console.log(DecimalPrecision.round(2.1753543549,8));
console.log(DecimalPrecision.round(2.1755465135353,4));
```

The easiest approach would be to use toFixed and then strip trailing zeros using the Number function:

```
const number = 15.5;
Number(number.toFixed(2)); // 15.5
```

```
const number = 1.7777777;
Number(number.toFixed(2)); // 1.78
```