I'd like to round at most two 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 two 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?
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
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,'');
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>
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
Another simple solution (without writing any function) may to use toFixed() and then convert to float again:
For example:
var objNumber = 1201203.1256546456;
objNumber = parseFloat(objNumber.toFixed(2))
See @AmrAli's answer for a more thorough run through and performance breakdown of all the various adaptations of this solution.
var DecimalPrecision = (function(){
if (Number.EPSILON === undefined) {
Number.EPSILON = Math.pow(2, -52);
}
if(Number.isInteger === undefined){
Number.isInteger = function(value) {
return typeof value === 'number' &&
isFinite(value) &&
Math.floor(value) === value;
};
}
this.isRound = function(n,p){
let l = n.toString().split('.')[1].length;
return (p >= l);
}
this.round = function(n, p=2){
if(Number.isInteger(n) || this.isRound(n,p))
return n;
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){
if(Number.isInteger(n) || this.isRound(n,p))
return n;
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
return Math.ceil((n + r) * o) / o;
}
this.floor = function(n, p=2){
if(Number.isInteger(n) || this.isRound(n,p))
return n;
let r = 0.5 * Number.EPSILON * n;
let o = 1; while(p-- > 0) o *= 10;
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));
console.log(DecimalPrecision.ceil(17,4));
console.log(DecimalPrecision.ceil(17.1,4));
console.log(DecimalPrecision.ceil(17.1,15));
function round(
value,
minimumFractionDigits,
maximumFractionDigits
) {
const formattedValue = value.toLocaleString('en', {
useGrouping: false,
minimumFractionDigits,
maximumFractionDigits
})
return Number(formattedValue)
}
console.log(round(21.891, 2, 3)) // 21.891
console.log(round(1.8, 2)) // 1.8, if you need 1.80, remove the `Number` function. Return directly the `formattedValue`.
console.log(round(21.0001, 0, 1)) // 21
console.log(round(0.875, 3)) // 0.875
Keep type as integer for later sorting or other math operations:
Math.round(1.7777777 * 100)/100
1.78
// Round up!
Math.ceil(1.7777777 * 100)/100
1.78
// Round down!
Math.floor(1.7777777 * 100)/100
1.77
Or convert to string:
(1.7777777).toFixed(2)
"1.77"
A simpler ES6 way is
const round = (x, n) =>
Number(parseFloat(Math.round(x * Math.pow(10, n)) / Math.pow(10, n)).toFixed(n));
This pattern also returns the precision asked for.
ex:
round(44.7826456, 4) // yields 44.7826
round(78.12, 4) // yields 78.12
A different approach is to use a library. Use Lodash:
const _ = require("lodash")
const roundedNumber = _.round(originalNumber, 2)
parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.
1.55 is the absolute correct result, because there exists no exact representation of 1.555 in the computer. If reading 1.555 it is rounded to the nearest possible value = 1.55499999999999994 (64 bit float). And rounding this number by toFixed(2) results in 1.55.
All other functions provided here give fault result, if the input is 1.55499999999999.
Solution: Append the digit "5" before scanning to rounding up (more exact: rounding away from 0) the number. Do this only, if the number is really a float (has a decimal point).
parseFloat("1.555"+"5").toFixed(2); // Returns 1.56
I reviewed every answer of this post. Here is my take on the matter:
const nbRounds = 7;
const round = (x, n=2) => {
const precision = Math.pow(10, n)
return Math.round((x+Number.EPSILON) * precision ) / precision;
}
let i = 0;
while( nbRounds > i++ ) {
console.log("round(1.00083899, ",i,") > ", round(1.00083899, i))
console.log("round(1.83999305, ",i,") > ", round(1.83999305, i))
}
A simple solution would be use Lodash's ceil function if you want to round up...
_.round(6.001, 2)
gives 6
_.ceil(6.001, 2);
gives 6.01
_.ceil(37.4929, 2);
gives 37.5
_.round(37.4929, 2);
gives 37.49
The question is to round to two decimals.
Let’s not make this complicated, modifying prototype chain, etc.
Here is one-line solution
let round2dec = num => Math.round(num * 100) / 100;
console.log(round2dec(1.77));
console.log(round2dec(1.774));
console.log(round2dec(1.777));
console.log(round2dec(10));
A simple generic solution
const round = (n, dp) => {
const h = +('1'.padEnd(dp + 1, '0')) // 10 or 100 or 1000 or etc
return Math.round(n * h) / h
}
console.log('round(2.3454, 3)', round(2.3454, 3)) // 2.345
console.log('round(2.3456, 3)', round(2.3456, 3)) // 2.346
console.log('round(2.3456, 2)', round(2.3456, 2)) // 2.35
Or just use Lodash round which has the same signature - for example, _.round(2.3456, 2)
This did the trick for me (TypeScript):
round(decimal: number, decimalPoints: number): number{
let roundedValue = Math.round(decimal * Math.pow(10, decimalPoints)) / Math.pow(10, decimalPoints);
console.log(`Rounded ${decimal} to ${roundedValue}`);
return roundedValue;
}
Rounded 18.339840000000436 to 18.34
Rounded 52.48283999999984 to 52.48
Rounded 57.24612000000036 to 57.25
Rounded 23.068320000000142 to 23.07
Rounded 7.792980000000398 to 7.79
Rounded 31.54157999999981 to 31.54
Rounded 36.79686000000004 to 36.8
Rounded 34.723080000000124 to 34.72
Rounded 8.4375 to 8.44
Rounded 15.666960000000074 to 15.67
Rounded 29.531279999999924 to 29.53
Rounded 8.277420000000006 to 8.28
Based on the chosen answer and the upvoted comment on the same question:
Math.round((num + 0.00001) * 100) / 100
This works for both these examples:
Math.round((1.005 + 0.00001) * 100) / 100
Math.round((1.0049 + 0.00001) * 100) / 100
The mathematical floor and round definitions:
lead us to
let round= x=> ( x+0.005 - (x+0.005)%0.01 +'' ).replace(/(\...)(.*)/,'$1');
// for a case like 1.384 we need to use a regexp to get only 2 digits after the dot
// and cut off machine-error (epsilon)
console.log(round(10));
console.log(round(1.7777777));
console.log(round(1.7747777));
console.log(round(1.384));
A simple general rounding function could be following:
number is: 1.2375 to be rounded to 3 decimal places
(note: 10^3 means Math.pow(10,3)).
function numberRoundDecimal(v,n) {
return Math.round((v+Number.EPSILON)*Math.pow(10,n))/Math.pow(10,n)}
// ------- tests --------
console.log(numberRoundDecimal(-0.024641163062896567,3)) // -0.025
console.log(numberRoundDecimal(0.9993360575508052,3)) // 0.999
console.log(numberRoundDecimal(1.0020739645577939,3)) // 1.002
console.log(numberRoundDecimal(0.975,0)) // 1
console.log(numberRoundDecimal(0.975,1)) // 1
console.log(numberRoundDecimal(0.975,2)) // 0.98
console.log(numberRoundDecimal(1.005,2)) // 1.01
I've read all the answers, the answers of similar questions and the complexity of the most "good" solutions didn't satisfy me. I don't want to put a huge round function set, or a small one but fails on scientific notation. So, I came up with this function. It may help someone in my situation:
function round(num, dec) {
const [sv, ev] = num.toString().split('e');
return Number(Number(Math.round(parseFloat(sv + 'e' + dec)) + 'e-' + dec) + 'e' + (ev || 0));
}
I didn't run any performance test because I will call this just to update the UI of my application. The function gives the following results for a quick test:
// 1/3563143 = 2.806510993243886e-7
round(1/3563143, 2) // returns `2.81e-7`
round(1.31645, 4) // returns 1.3165
round(-17.3954, 2) // returns -17.4
This is enough for me.
Instead of using Math.round as @brian-ustas suggest, I prefer the Math.trunc approach to fix the the following situation:
const twoDecimalRound = num => Math.round(num * 100) / 100;
const twoDecimalTrunc = num => Math.trunc(num * 100) / 100;
console.info(twoDecimalRound(79.996)); // not desired output: 80;
console.info(twoDecimalTrunc(79.996)); // desired output: 79.99;
I was building a simple tipCalculator and there was a lot of answers here that seemed to overcomplicate the issue. So I found summarizing the issue to be the best way to truly answer this question.
If you want to create a rounded decimal number, first you call toFixed(# of decimal places you want to keep) and then wrap that in a Number().
So the end result:
let amountDue = 286.44;
tip = Number((amountDue * 0.2).toFixed(2));
console.log(tip) // 57.29 instead of 57.288
The rounding problem can be avoided by using numbers represented in exponential notation.
public roundFinancial(amount: number, decimals: number) {
return Number(Math.round(Number(`${amount}e${decimals}`)) + `e-${decimals}`);
}
This function works for me. You just pass in the number and the places you want to round and it does what it needs to do easily.
round(source, n) {
let places = Math.pow(10, n);
return Math.round(source * places) / places;
}
The big challenge on this seemingly simple task is that we want it to yield psychologically expected results even if the input contains minimal rounding errors to start with (not mentioning the errors which will happen within our calculation). If we know that the real result is exactly 1.005, we expect that rounding to two digits yields 1.01, even if the 1.005 is the result of a large computation with loads of rounding errors on the way.
The problem becomes even more obvious when dealing with floor() instead of round(). For example, when cutting everything away after the last two digits behind the dot of 33.3, we would certainly not expect to get 33.29 as a result, but that is what happens:
console.log(Math.floor(33.3 * 100) / 100)
In simple cases, the solution is to perform calculation on strings instead of floating point numbers, and thus avoid rounding errors completely. However, this option fails at the first non-trivial mathematical operation (including most divsions), and it is slow.
When operating on floating point numbers, the solution is to introduce a parameter which names the amount by which we are willing to deviate from the actual computation result, in order to output the psychologically expected result.
var round = function(num, digits = 2, compensateErrors = 2) {
if (num < 0) {
return -this.round(-num, digits, compensateErrors);
}
const pow = Math.pow(10, digits);
return (Math.round(num * pow * (1 + compensateErrors * Number.EPSILON)) / pow);
}
/* --- testing --- */
console.log("Edge cases mentioned in this thread:")
var values = [ 0.015, 1.005, 5.555, 156893.145, 362.42499999999995, 1.275, 1.27499, 1.2345678e+2, 2.175, 5.015, 58.9 * 0.15 ];
values.forEach((n) => {
console.log(n + " -> " + round(n));
console.log(-n + " -> " + round(-n));
});
console.log("\nFor numbers which are so large that rounding cannot be performed anyway within computation precision, only string-based computation can help.")
console.log("Standard: " + round(1e+19));
console.log("Compensation = 1: " + round(1e+19, 2, 1));
console.log("Effectively no compensation: " + round(1e+19, 2, 0.4));
Note: Internet Explorer does not know Number.EPSILON. If you are in the unhappy position of still having to support it, you can use a shim, or just define the constant yourself for that specific browser family.
A slight variation on this is if you need to format a currency amount as either being a whole amount of currency or an amount with fractional currency parts.
For example:
1 should output $1
1.1 should output $1.10
1.01 should output $1.01
Assuming amount is a number:
const formatAmount = (amount) => amount % 1 === 0 ? amount : amount.toFixed(2);
If amount is not a number then use parseFloat(amount) to convert it to a number.
As per the answer already given in comments with the link to http://jsfiddle.net/AsRqx/, the following one worked perfectly for me.
function C(num)
{
return +(Math.round(num + "e+2") + "e-2");
}
function N(num, places)
{
return +(Math.round(num + "e+" + places) + "e-" + places);
}
C(1.005);
N(1.005, 0);
N(1.005, 1); // Up to 1 decimal places
N(1.005, 2); // Up to 2 decimal places
N(1.005, 3); // Up to 3 decimal places
This works correctly with positive, negative and large numbers:
function Round(value) {
const neat = +(Math.abs(value).toPrecision(15));
const rounded = Math.round(neat * 100) / 100;
return rounded * Math.sign(value);
}
//0.244 -> 0.24
//0.245 -> 0.25
//0.246 -> 0.25
//-0.244 -> -0.24
//-0.245 -> -0.25
//-0.246 -> -0.25
From the existing answers I found another solution which seems to work great, which also works with sending in a string and eliminates trailing zeros.
function roundToDecimal(string, decimals) {
return parseFloat(parseFloat(string).toFixed(decimals));
}
It doesn't take in to account if you send in some bull.. like "apa" though. Or it will probably throw an error which I think is the proper way anyway, it's never good to hide errors that should be fixed (by the calling function).
This worked pretty well for me when wanting to always round up to a certain decimal. The key here is that we will always be rounding up with the Math.ceil function.
You could conditionally select ceil or floor if needed.
/**
* Possibility to lose precision at large numbers
* @param number
* @returns Number number
*/
var roundUpToNearestHundredth = function(number) {
// Ensure that we use high precision Number
number = Number(number);
// Save the original number so when we extract the Hundredth decimal place we don't bit switch or lose precision
var numberSave = Number(number.toFixed(0));
// Remove the "integer" values off the top of the number
number = number - numberSave;
// Get the Hundredth decimal places
number *= 100;
// Ceil the decimals. Therefore .15000001 will equal .151, etc.
number = Math.ceil(number);
// Put the decimals back into their correct spot
number /= 100;
// Add the "integer" back onto the number
return number + numberSave;
};
console.log(roundUpToNearestHundredth(6132423.1200000000001))
Here's my solution to this problem:
function roundNumber(number, precision = 0) {
var num = number.toString().replace(",", "");
var integer, decimal, significantDigit;
if (num.indexOf(".") > 0 && num.substring(num.indexOf(".") + 1).length > precision && precision > 0) {
integer = parseInt(num).toString();
decimal = num.substring(num.indexOf(".") + 1);
significantDigit = Number(decimal.substr(precision, 1));
if (significantDigit >= 5) {
decimal = (Number(decimal.substr(0, precision)) + 1).toString();
return integer + "." + decimal;
} else {
decimal = (Number(decimal.substr(0, precision)) + 1).toString();
return integer + "." + decimal;
}
}
else if (num.indexOf(".") > 0) {
integer = parseInt(num).toString();
decimal = num.substring(num.indexOf(".") + 1);
significantDigit = num.substring(num.length - 1, 1);
if (significantDigit >= 5) {
decimal = (Number(decimal) + 1).toString();
return integer + "." + decimal;
} else {
return integer + "." + decimal;
}
}
return number;
}
A slight modification of this answer that seems to work well.
Function
function roundToStep(value, stepParam) {
var step = stepParam || 1.0;
var inv = 1.0 / step;
return Math.round(value * inv) / inv;
}
Usage
roundToStep(2.55) = 3
roundToStep(2.55, 0.1) = 2.6
roundToStep(2.55, 0.01) = 2.55
This answer is more about speed.
var precalculatedPrecisions = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10];
function round(num, _prec) {
_precision = precalculatedPrecisions[_prec]
return Math.round(num * _precision + 1e-14) / _precision ;
}
jsPerf about this.
I have found this works for all my use cases:
const round = (value, decimalPlaces = 0) => {
const multiplier = Math.pow(10, decimalPlaces);
return Math.round(value * multiplier + Number.EPSILON) / multiplier;
};
Keep in mind that is ES6. An ES5 equivalent would be very easy to code though, so I'm not is going to add it.
A helper function where rounging is your default rounding:
let rounding = 4;
let round = (number) => { let multiply = Math.pow(10,rounding); return Math.round(number*multiply)/multiply};
console.log(round(0.040579431));
=> 0.0406
There is a solution working for all numbers. Give it a try. The expression is given below.
Math.round((num + 0.00001) * 100) / 100. Try Math.round((1.005 + 0.00001) * 100) / 100 and Math.round((1.0049 + 0.00001) * 100) / 100
I recently tested every possible solution and finally arrived at the output after trying almost 10 times.
Here is a screenshot of issue arose during calculations,
Head over to the amount field. It's returning almost infinite. I gave it a try for the toFixed() method, but it's not working for some cases (i.e., try with pi) and finally derived a solution given above.
Here's a modified version of astorije's answer that better supports rounding negative values.
// https://stackoverflow.com/a/21323513/384884
// Modified answer from astorije
function round(value, precision) {
// Ensure precision exists
if (typeof precision === "undefined" || +precision === 0) {
// Just do a regular Math.round
return Math.round(value);
}
// Convert the value and precision variables both to numbers
value = +value;
precision = +precision;
// Ensure the value is a number and that precision is usable
if (isNaN(value) || !(typeof precision === "number" && precision % 1 === 0)) {
// Return NaN
return NaN;
}
// Get the sign of value
var signValue = Math.sign(value);
// Get the absolute value of value
value = Math.abs(value);
// Shift
value = value.toString().split("e");
value = Math.round(+(value[0] + "e" + (value[1] ? (+value[1] + precision) : precision)));
// Shift back
value = value.toString().split("e");
value = +(value[0] + "e" + (value[1] ? (+value[1] - precision) : -precision));
// Apply the sign
value = value * signValue;
// Return rounded value
return value;
}
My solution considers the input as a string and uses the algorithm of "mathematical rounding" to n digits: take n digits, and add one if digit n+1 is 5 or more. It also allows specifying negative digits, for example rounding 123.45 to -1 digits is 120. It works with scientific notation (e.g. 1.2e-3), as well. I did not measure its speed and I don't think it was the best performance-wise.
function safeRound( numInput, numPrecision ) {
const strNumber = numInput.toString().replace( 'E', 'e' );
const bSign = '+-'.indexOf( strNumber[ 0 ] ) !== -1;
const strSign = bSign ? strNumber[ 0 ] : '';
const numSign = strSign !== '-' ? +1 : -1;
const ixExponent = ( ixFound => ixFound !== -1 ? ixFound : strNumber.length )( strNumber.indexOf( 'e' ) );
const strExponent = strNumber.substr( ixExponent + 1 );
const numExponent = ixExponent !== strNumber.length ? Number.parseInt( strExponent ) : 0;
const ixDecimal = ( ixFound => ixFound !== -1 ? ixFound : ixExponent )( strNumber.indexOf( '.' ) );
const strInteger = strNumber.substring( !bSign ? 0 : 1, ixDecimal );
const strFraction = strNumber.substring( ixDecimal + 1, ixExponent );
const numPrecisionAdjusted = numPrecision + numExponent;
const strIntegerKeep = strInteger.substring( 0, strInteger.length + Math.min( 0, numPrecisionAdjusted ) ) + '0'.repeat( -Math.min( 0, numPrecisionAdjusted ) );
const strFractionKeep = strFraction.substring( 0, Math.max( 0, numPrecisionAdjusted ) );
const strRoundedDown = strSign + ( strIntegerKeep === '' ? '0' : strIntegerKeep ) + ( strFractionKeep === '' ? '' : '.' + strFractionKeep ) + ( strExponent === '' ? '' : 'e' + strExponent );
const chRoundUp = 0 <= numPrecisionAdjusted ? strFraction.substr( numPrecisionAdjusted, 1 ) : ( '0' + strInteger ).substr( numPrecisionAdjusted, 1 );
const bRoundUp = '5' <= chRoundUp && chRoundUp <= '9';
const numRoundUp = bRoundUp ? numSign * Math.pow( 10, -numPrecision ) : 0;
return Number.parseFloat( strRoundedDown ) + numRoundUp;
}
function safeRoundTest( numInput, numPrecision, strExpected ) {
const strActual = safeRound( numInput, numPrecision ).toString();
const bPassed = strActual === strExpected;
console.log( 'numInput', numInput, 'numPrecision', numPrecision, 'strExpected', strExpected, 'strActual', strActual, 'bPassed', bPassed );
return bPassed ? 0 : 1;
}
function safeRoundTests() {
let numFailed = 0;
numFailed += safeRoundTest( 0, 0, '0' );
numFailed += safeRoundTest( '0', 0, '0' );
numFailed += safeRoundTest( '0.1', 0, '0' );
numFailed += safeRoundTest( '+0.1', 0, '0' );
numFailed += safeRoundTest( '-0.1', 0, '0' );
numFailed += safeRoundTest( '0.1', 1, '0.1' );
numFailed += safeRoundTest( '+0.1', 1, '0.1' );
numFailed += safeRoundTest( '-0.1', 1, '-0.1' );
numFailed += safeRoundTest( '0.9', 0, '1' );
numFailed += safeRoundTest( '+0.9', 0, '1' );
numFailed += safeRoundTest( '-0.9', 0, '-1' );
numFailed += safeRoundTest( '0.9', 1, '0.9' );
numFailed += safeRoundTest( '+0.9', 1, '0.9' );
numFailed += safeRoundTest( '-0.9', 1, '-0.9' );
numFailed += safeRoundTest( '0.5', 0, '1' );
numFailed += safeRoundTest( '+0.5', 0, '1' );
numFailed += safeRoundTest( '-0.5', 0, '-1' );
numFailed += safeRoundTest( '0.4999', 0, '0' );
numFailed += safeRoundTest( '+0.4999', 0, '0' );
numFailed += safeRoundTest( '-0.4999', 0, '0' );
numFailed += safeRoundTest( '1.005', 2, '1.01' );
numFailed += safeRoundTest( '1.00499999999', 2, '1' );
numFailed += safeRoundTest( '012.3456', -4, '0' );
numFailed += safeRoundTest( '012.3456', -3, '0' );
numFailed += safeRoundTest( '012.3456', -2, '0' );
numFailed += safeRoundTest( '012.3456', -1, '10' );
numFailed += safeRoundTest( '012.3456', 0, '12' );
numFailed += safeRoundTest( '012.3456', 1, '12.3' );
numFailed += safeRoundTest( '012.3456', 2, '12.35' );
numFailed += safeRoundTest( '012.3456', 3, '12.346' );
numFailed += safeRoundTest( '012.3456', 4, '12.3456' );
numFailed += safeRoundTest( '012.3456', 5, '12.3456' );
numFailed += safeRoundTest( '12.', 0, '12' );
numFailed += safeRoundTest( '.12', 2, '0.12' );
numFailed += safeRoundTest( '0e0', 0, '0' );
numFailed += safeRoundTest( '1.2e3', 0, '1200' );
numFailed += safeRoundTest( '1.2e+3', 0, '1200' );
numFailed += safeRoundTest( '1.2e-3', 0, '0' );
numFailed += safeRoundTest( '1.2e-3', 3, '0.001' );
numFailed += safeRoundTest( '1.2e-3', 4, '0.0012' );
numFailed += safeRoundTest( '1.2e-3', 5, '0.0012' );
numFailed += safeRoundTest( '+12.', 0, '12' );
numFailed += safeRoundTest( '+.12', 2, '0.12' );
numFailed += safeRoundTest( '+0e0', 0, '0' );
numFailed += safeRoundTest( '+1.2e3', 0, '1200' );
numFailed += safeRoundTest( '+1.2e+3', 0, '1200' );
numFailed += safeRoundTest( '+1.2e-3', 0, '0' );
numFailed += safeRoundTest( '+1.2e-3', 3, '0.001' );
numFailed += safeRoundTest( '+1.2e-3', 4, '0.0012' );
numFailed += safeRoundTest( '+1.2e-3', 5, '0.0012' );
numFailed += safeRoundTest( '-12.', 0, '-12' );
numFailed += safeRoundTest( '-.12', 2, '-0.12' );
numFailed += safeRoundTest( '-0e0', 0, '0' );
numFailed += safeRoundTest( '-1.2e3', 0, '-1200' );
numFailed += safeRoundTest( '-1.2e+3', 0, '-1200' );
numFailed += safeRoundTest( '-1.2e-3', 0, '0' );
numFailed += safeRoundTest( '-1.2e-3', 3, '-0.001' );
numFailed += safeRoundTest( '-1.2e-3', 4, '-0.0012' );
numFailed += safeRoundTest( '-1.2e-3', 5, '-0.0012' );
numFailed += safeRoundTest( '9876.543e210', 0, '9.876543e+213' );
numFailed += safeRoundTest( '9876.543e210', -210, '9.877e+213' );
numFailed += safeRoundTest( '9876.543e210', -209, '9.8765e+213' );
numFailed += safeRoundTest( '9876.543e+210', 0, '9.876543e+213' );
numFailed += safeRoundTest( '9876.543e+210', -210, '9.877e+213' );
numFailed += safeRoundTest( '9876.543e+210', -209, '9.8765e+213' );
numFailed += safeRoundTest( '9876.543e-210', 213, '9.876543e-207' );
numFailed += safeRoundTest( '9876.543e-210', 210, '9.877e-207' );
numFailed += safeRoundTest( '9876.543e-210', 211, '9.8765e-207' );
console.log( 'numFailed', numFailed );
}
safeRoundTests();
I created this function, for rounding a number. The value can be a string (ex. '1.005') or a number 1.005 that will be 1 by default and if you specify the decimal to be 2, the result will be 1.01
round(value: string | number, decimals: number | string = "0"): number | null {
return +( Math.round(Number(value + "e+"+decimals)) + "e-" + decimals);
}
Usage: round(1.005, 2) // 1.01 or Usage: round('1.005', 2) //1.01
The proposed answers, while generally correct, don't consider the precision of the passed in number, which is not expressed as requirement in the original question, but it may be a requirement in case of scientific application where 3 is different from 3.00 (for example) as the number of decimal digits represents the precision of the instrument that have acquired the value or the accuracy of a calculation.
In fact, the proposed answers rounds 3.001 to 3 while by keeping the information about the precision of the number should be 3.00.
Below is a function that takes that in account:
function roundTo(value, decimal) {
let absValue = Math.abs(value);
let int = Math.floor(absValue).toString().length;
let dec = absValue.toString().length - int;
dec -= (Number.isInteger(absValue) ? 0 : 1);
return value.toPrecision(int + Math.min(dec, decimal));
}
Use something like this to round up:
num = 519.805;
dp = Math.pow(10, 2);
num = parseFloat(num.toString().concat("1"));
rounded = Math.round((num + Number.EPSILON)* dp)/dp;
As it would deal with numbers falling short where there is only one decimal place to round at the end.
A function with readable options is much more inuitive:
function round_number(options) {
const places = 10**options.decimal_places;
const res = Math.round(options.number * places)/places;
return(res)
}
Usage:
round_number({
number : 0.5555555555555556,
decimal_places : 3
})
0.556
Here I used a ternary operator to check if the number has fractional values. If it doesn't then I simply return the number.
Otherwise, I use the Intl.NumberFormat constructor to get the desired value.
Intl.NumberFormat is part of the ECMAScript Internationalization API Specification (ECMA402). It has pretty good browser support, including even IE11, and it is fully supported in Node.js.
const numberFormatter = new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
function getRoundedNumber(number) {
return number.toString().indexOf(".") == -1 ? number : numberFormatter.format(number);
}
console.log(getRoundedNumber(10));
console.log(getRoundedNumber(1.7777777));
console.log(getRoundedNumber(9.1));
console.log(getRoundedNumber(2.345));
console.log(getRoundedNumber(2.2095));
console.log(getRoundedNumber(2.995));
only if necessary You said?
So I suggest You this...
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>roundPrecision</title>
<script>
class MyMath{
static roundPrecision(number,precision,fillZeros){
// number You want to round
// precision nb of decimals
// fillZeros the number of 0 You want to add IF necessary!
// 0 = no fill with zeros.
let num = number;
let prec = precision;
let exp = Math.pow(10,prec);
let round = Math.round(number * exp)/exp
if (fillZeros>0){
return round.toFixed(fillZeros)
}
return round;
}
}
</script>
</head>
<body>
<p class="myMath" id="field1"></p>
<p class="myMath" id="field2"></p>
<p class="myMath" id="field3"></p>
<script>
document.getElementById("field1").innerHTML = MyMath.roundPrecision(5,0,3); // 5.000
document.getElementById("field2").innerHTML = MyMath.roundPrecision(Math.PI,2,4); // 3.1400
document.getElementById("field3").innerHTML = MyMath.roundPrecision(2.4,1,2); // 2.40
</script>
</body>
</html>