408

I need to round for example 6.688689 to 6.7, but it always shows me 7.

My method:

Math.round(6.688689);
//or
Math.round(6.688689, 1);
//or 
Math.round(6.688689, 2);

But result always is the same 7... What am I doing wrong?

Vitalii Ponomar
  • 10,686
  • 20
  • 60
  • 88
  • 49
    `(6.688689​).toFixed(1);` – Shadow The GPT Wizard Feb 26 '12 at 13:25
  • Check [this](http://stackoverflow.com/questions/661562/how-to-format-a-float-in-javascript) – raina77ow Feb 26 '12 at 13:25
  • possible duplicate of [round number in JavaScript to N decimal places](http://stackoverflow.com/questions/2221167/round-number-in-javascript-to-n-decimal-places) -- please use the search before you ask a new question. – Felix Kling Feb 26 '12 at 13:41
  • 1
    possible duplicate of [JavaScript: formatting number with exactly two decimals](http://stackoverflow.com/questions/1726630/javascript-formatting-number-with-exactly-two-decimals) – bummi Jul 04 '15 at 08:05
  • 1
    @ShadowWizard is correct. However, `.toFixed` returns a string. Make sure to wrap the result in `Number()`. See accepted answer, and others. – Jordan Arsenault Jan 01 '19 at 21:15

19 Answers19

691
Number((6.688689).toFixed(1)); // 6.7
davin
  • 44,863
  • 9
  • 78
  • 78
  • 33
    Convert a number to a string and then back again? That can't be fast. – csl Nov 09 '12 at 14:07
  • not good if your number has less decimals than needed. It adds some – njzk2 Feb 12 '15 at 21:28
  • 3
    as JS benchmark show, it is slower than @fivedigit method – fadomire Mar 02 '15 at 13:42
  • 19
    `Number((456.1235).toFixed(3)) -> 456.123`, `Number((1.235).toFixed(2)) -> 1.24`... Stupid JavaSript... – NoOne Jun 21 '15 at 09:31
  • 9
    This might NOT DO what you expect! The result can even depend on the browser, see this question: http://stackoverflow.com/q/566564/2224996 – maja Jul 18 '15 at 13:09
  • came in handy when working with a variable that was occasionally undefined.. When var is non-numeric.. var.toFixed(2) returns an error.. but Number(var).toFixed(2) returns NaN . Thanks! – JustinP Mar 24 '17 at 13:21
  • Some perf stats: https://jsperf.com/parsefloat-tofixed-vs-math-round/12. Math.round is faster, and practically speaking seems like it should be safe even though it technically does perform floating point math. – Scottmas Feb 12 '20 at 21:50
  • it should be Math.round() as toFixed() doesn't always round properly. – Coderxyz Dec 18 '22 at 18:46
213
var number = 6.688689;
var roundedNumber = Math.round(number * 10) / 10;
fivedigit
  • 18,464
  • 6
  • 54
  • 58
  • 20
    This doesn't always work. Take `Math.round(1.005*100)/100` for example from [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round) – tybro0103 May 03 '16 at 17:54
  • 12
    @tybro0103 Floating point evil: `1.005 * 100 = 100.49999999999999` (at least in the JS engine I tried). That's why it doesn't work and why you should never rely on floats being perfectly accurate. – sudo Jan 22 '18 at 06:10
  • 4
    Wrong. Math.round(1.015 * 100) / 100 returns 1.01 instead of 1.02 – Marco Marsala Sep 18 '19 at 08:47
  • @MarcoMarsala Wrong. Who said that 0.5 rounds up to 1? There is no 100% correct convention and either variant is correct. – ScienceDiscoverer Mar 28 '21 at 19:15
116

Use toFixed() function.

(6.688689).toFixed(); // equal to "7"
(6.688689).toFixed(1); // equal to "6.7"
(6.688689).toFixed(2); // equal to "6.69"
Lars
  • 710
  • 5
  • 19
rpeshkov
  • 4,877
  • 3
  • 27
  • 43
  • 9
    This might NOT DO what you expect! The result can even depend on the browser, see this question: http://stackoverflow.com/q/566564/2224996 – maja Jul 18 '15 at 13:09
  • 10
    (6.688689).toFixed(); is equal to "7" not 7. Same for other examples. – Vado Nov 30 '15 at 05:38
  • 1
    This answer is misleading. for example `(1).toFixed(4)` returns '1.0000' – bikeman868 Jun 20 '21 at 21:08
  • @bikeman868 How is it misleading? According to your example, you only gave a single number and it gave you 4 decimal places. It does what it says – Santhosh Jun 16 '22 at 13:36
  • Your answer suggests that the number of decimal places is truncated, because in every example some decimal places are rounded. The toFixed function adds trailing zeros and this isn't clear from your answer, so this result might be surprising based on our examples. – bikeman868 Jun 21 '22 at 16:51
36

Upd (2019-10). Thanks to Reece Daniels code below now available as a set of functions packed in npm-package expected-round (take a look).


You can use helper function from MDN example. Than you'll have more flexibility:

Math.round10(5.25, 0);  // 5
Math.round10(5.25, -1); // 5.3
Math.round10(5.25, -2); // 5.25
Math.round10(5, 0);     // 5
Math.round10(5, -1);    // 5
Math.round10(5, -2);    // 5

Upd (2019-01-15). Seems like MDN docs no longer have this helper funcs. Here's a backup with examples:

// Closure
(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;
    }
    // If the value is negative...
    if (value < 0) {
      return -decimalAdjust(type, -value, exp);
    }
    // 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);
    };
  }
})();

Usage 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
Math.round10(-1.005, -2);  // -1.01
// 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
a.s.panchenko
  • 1,196
  • 16
  • 22
  • 4
    ?? "Math.round10 is not a function" – Peter Krauss Dec 31 '18 at 03:37
  • 1
    I found this extremely useful so whacked it in a quick npm package for those looking to use it without bloating extra code. Credited @a.s.panchenko with the original answer also: https://www.npmjs.com/package/expected-round – Reece Daniels Oct 17 '19 at 14:42
34
> +(6.688687).toPrecision(2)
6.7

A Number object in JavaScript has a method that does exactly what you need. That method is Number.toPrecision([precision]).

Just like with .toFixed(1) it converts the result into a string, and it needs to be converted back into a number. Done using the + prefix here.

simple benchmark on my laptop:

number = 25.645234 typeof number
50000000 x number.toFixed(1) = 25.6 typeof string / 17527ms
50000000 x +(number.toFixed(1)) = 25.6 typeof number / 23764ms
50000000 x number.toPrecision(3) = 25.6 typeof string / 10100ms
50000000 x +(number.toPrecision(3)) = 25.6 typeof number / 18492ms
50000000 x Math.round(number*10)/10 = 25.6 typeof number / 58ms
string = 25.645234 typeof string
50000000 x Math.round(string*10)/10 = 25.6 typeof number / 7109ms

you can repeat this benchmark on your own setup with node or your browser's console:

function bench(name, func) {
  console.log(name, typeof func(), func())
  console.time(name)
  Array(50000000).forEach(func)
  console.timeEnd(name)
}

number = 25.645234
string = '25.645234'
bench( 'toFixed', () => number.toFixed(1) )
bench( '+toFixed', () => +(number.toFixed(1)) )
bench( 'toPrecision', () => number.toPrecision(3) )
bench( '+toPrecision', () => +(number.toPrecision(3)) )
bench( 'Math.round(num)', () => Math.round(number*10)/10 )
bench( 'Math.round(str)', () => Math.round(string*10)/10 )
Evgeny
  • 6,533
  • 5
  • 58
  • 64
  • In my opinion this is the best answer (best in term of best practice, most straightforward approach). – cezar Aug 22 '19 at 10:58
  • 4
    `1e-10.toPrecision(3)`: "1.00e-10" - this rounds to _significant digits_. – Vsevolod Golovanov Apr 07 '20 at 11:33
  • 1
    Beware, as @VsevolodGolovanov said, it's significant digits, not decimals. For example, consider `1234.5678`: `toFixed(6) => "1234.567800"`, `toFixed(2) => "1234.57"`, `toPrecision(6) => "1234.57"`, and `toPrecision(2) => "1.2e+3"`. – Andrew Aug 28 '21 at 03:35
  • every scope is different, but in **my** scope, this helped me =) thanks – Rodrigo E. Principe Oct 15 '21 at 13:41
13

If you not only want to use toFixed() but also ceil() and floor() on a float then you can use the following function:

function roundUsing(func, number, prec) {
    var tempnumber = number * Math.pow(10, prec);
    tempnumber = func(tempnumber);
    return tempnumber / Math.pow(10, prec);
}

Produces:

> roundUsing(Math.floor, 0.99999999, 3)
0.999
> roundUsing(Math.ceil, 0.1111111, 3)
0.112

UPD:

The other possible way is this:

Number.prototype.roundUsing = function(func, prec){
    var temp = this * Math.pow(10, prec)
    temp = func(temp);
    return temp / Math.pow(10, prec)
}

Produces:

> 6.688689.roundUsing(Math.ceil, 1)
6.7
> 6.688689.roundUsing(Math.round, 1)
6.7
> 6.688689.roundUsing(Math.floor, 1)
6.6
Dennis Yarmosh
  • 204
  • 2
  • 3
  • how do we then decide when to use ceil, floor or round for rounding? For ex: roundUsing(Math.round, 1.015, 2) roundUsing(Math.ceil, 1.015, 2) give 2 different values How do we know which one to use – gaurav5430 Dec 26 '19 at 04:56
  • @gaurav5430, that completely depends on the business logic. It's you who should know if you need to always round up, down, to the nearest value, or others. – Andrew Aug 28 '21 at 04:09
13

My extended round function:

function round(value, precision) {
  if (Number.isInteger(precision)) {
    var shift = Math.pow(10, precision);
    // Limited preventing decimal issue
    return (Math.round( value * shift + 0.00000000000001 ) / shift);
  } else {
    return Math.round(value);
  }
} 

Example Output:

round(123.688689)     // 123
round(123.688689, 0)  // 123
round(123.688689, 1)  // 123.7
round(123.688689, 2)  // 123.69
round(123.688689, -2) // 100
round(1.015, 2) // 1.02
Nick Tsai
  • 3,799
  • 33
  • 36
7

There is the alternative .toLocaleString() to format numbers, with a lot of options regarding locales, grouping, currency formatting, notations. Some examples:


Round to 1 decimal, return a float:

const n = +6.688689.toLocaleString('fullwide', {maximumFractionDigits:1})
console.log(
  n, typeof n
)

Round to 2 decimals, format as currency with specified symbol, use comma grouping for thousands:

console.log(
  68766.688689.toLocaleString('fullwide', {maximumFractionDigits:2, style:'currency', currency:'USD', useGrouping:true})   
)

Format as locale currency:

console.log(
  68766.688689.toLocaleString('fr-FR', {maximumFractionDigits:2, style:'currency', currency:'EUR'})   
)

Round to minimum 3 decimal, force zeroes to display:

console.log(
  6.000000.toLocaleString('fullwide', {minimumFractionDigits:3})
)

Percent style for ratios. Input * 100 with % sign

console.log(
  6.688689.toLocaleString('fullwide', {maximumFractionDigits:2, style:'percent'})
)
Community
  • 1
  • 1
NVRM
  • 11,480
  • 1
  • 88
  • 87
7

See below

var original = 28.59;

var result=Math.round(original*10)/10 will return you returns 28.6

Hope this is what you want..

Jack
  • 9,448
  • 3
  • 29
  • 33
Fahim Parkar
  • 30,974
  • 45
  • 160
  • 276
5

I have very good solution with if toFixed() is not working.

function roundOff(value, decimals) {
  return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}

Example

roundOff(10.456,2) //output 10.46
Ashish Gondaliya
  • 318
  • 1
  • 3
  • 7
4
Math.round((6.688689 + Number.EPSILON) * 10) / 10

Solution stolen from https://stackoverflow.com/a/11832950/2443681

This should work with nearly any float value. It doesn't force decimal count though. It's not clear whether this was a requirement. Should be faster than using toFixed(), which has other issues as well based on the comments to other answers.

A nice utility function to round in needed decimal precision:

const roundToPrecision = (value, decimals) => {
  const pow = Math.pow(10, decimals);
  return Math.round((value + Number.EPSILON) * pow) / pow;
};
Makke R.
  • 61
  • 4
3
float(value,ndec);
function float(num,x){
this.num=num;
this.x=x;
var p=Math.pow(10,this.x);
return (Math.round((this.num).toFixed(this.x)*p))/p;
}
3
+((6.688689 * (1 + Number.EPSILON)).toFixed(1)); // 6.7
+((456.1235 * (1 + Number.EPSILON)).toFixed(3)); // 456.124
  • The + sign at the beginning is to convert from string => float if anyone's curious. Pretty cool this is the only answer to use Epsilon. Displays big brain in understanding of how floating point numbers work. http://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON – Llama D'Attore Apr 04 '21 at 15:05
2

if you're under node.js context, you can try mathjs

const math = require('mathjs')
math.round(3.1415926, 2) 
// result: 3.14
hexcola
  • 41
  • 3
1

I think this function can help.

 function round(value, ndec){
    var n = 10;
    for(var i = 1; i < ndec; i++){
        n *=10;
    }

    if(!ndec || ndec <= 0)
        return Math.round(value);
    else
        return Math.round(value * n) / n;
}


round(2.245, 2) //2.25
round(2.245, 0) //2
1

Minor tweak to this answer:

function roundToStep(value, stepParam) {
   var step = stepParam || 1.0;
   var inv = 1.0 / step;
   return Math.round(value * inv) / inv;
}

roundToStep(2.55, 0.1) = 2.6
roundToStep(2.55, 0.01) = 2.55
roundToStep(2, 0.01) = 2
Crashalot
  • 33,605
  • 61
  • 269
  • 439
1

How to correctly round decimals in a number (basics):
We start from far right number:

  • If this number is >= to 5 rounding is required, we will then report a 1 to the first number on the left.
  • If this number is < to 5 means no rounding

Once you know if you need to report a value or not you can delete the last number and repeat the operation.

  • If there is a value to be reported you will first add it to the new far right number before repeating the previous tests.

Beware there is a special case when you need to report a value and the number that must be added to that value is 9 : in such case you will have to change the number value for 0 before reporting a 1 on the following left number.

For some of the failing answers it looks like decimals are splitted left to right for the required amount of decimals without even caring about the rounding.

Now that this is stated here is a function that will round a provided float value recursively using the above logic.

function roundFloatR(n, precision = 0, opts = { return: 'number' }) { // Use recursivity

    if ( precision == 0 ) { // n will be rounded to the closest integer

        if (opts.return == 'number') return Math.round(n);
        else if (opts.return == 'string') return `${Math.round(n)}`;
    
    } else {

        let ns = `${n}`.split(''); // turns float into a string before splitting it into a char array    

        if ( precision < 0 ) { // precision is a negative number
            precision += ns.length - 1; // precision equals last index of ns - its actual value 

        } else if ( precision > 0 ) { // precision is a positive number
            if ( ns.indexOf('.') > -1 ) 
                precision += ns.indexOf('.'); // precision equals its value + the index of the float separator in the string / array of char
        }

        // RECURSIVE FUNCTION: loop from the end of ns to the precision index while rounding the values
        // index: index in the ns char array, rep: reported value, (INTERNAL_VAR, cn: current number)
        const recursive = (index, rep) => { 
            let cn = parseInt(ns[index]); // get the current number from ns at index

            if (index <= precision) { // current index inferior or equal to the defined precision index (end of rounding) 

                if (rep) { // if a reported value exists
                    cn += rep; // add reported value to current number 

                    if (cn == 10) { // extends rounding for special case of decimals ending with 9 + reported value 
                        ns[index] = '0';
                        recursive( (index - 1), 1 ); // calls recursive() again with a reported value

                    } else if (cn < 10) 
                        ns[index] = `${cn}`;    
                }

            } else if (index > precision) { // current index superior to defined precision index  

                ns.pop(); // each passage in this block will remove the last entry of ns
                if (rep) cn += rep; // adds reported value (if it exists) to current number
                
                if ( cn >= 5 ) // ROUNDING
                    recursive( (index - 1), 1 ); // calls recursive() again with a reported value

                else  // NO ROUNDING
                    recursive( index - 1 ); // calls recursive() again w/o a reported value 
            }  

        }; // end of recursive()

        recursive(ns.length - 1); // starts recursive rounding over the ns char array (arg is the last index of ns)

        if (opts.return == "number") return parseFloat(ns.join('')); // returns float number
        else if (opts.return == "string") return ns.join(''); // returns float number as string
    }

} //

How it works:
We first turn the provided float value into a string before splitting it into an array of char using the String.split('') instruction.

Then we will call the recursive() function with the last index of the array of chars as argument, to iterate through that array from last index to the precision index while rounding the value.

Arguments explanation:
There is a total of 3 arguments which allow different functionnalities.

  • n: the value to be rounded (number or string).
  • precision: [default = 0]
    an int which represent the amount of decimals we want to round the provided number to.
    There are 3 possibilities:
    • precision == 0: value returned will be the same as using the Math.round() method
    • precision > 0: precision will be defined from the float separator index + precision value
    • precision < 0: precision will be defined from the index of the last number - precision value
  • opts: [default = {return: 'number'}]
    an options object with a unique property called return which take a string value options are 'number' or 'string'.
    allows the selection of the type of value returned by the function

2nd and 3rd arguments are optionnals

Usage and examples:

using a float value

let n = 20.336099982261654;

let r = roundFloatR(n); // r = 20
r = roundFloatR(n, 2); // r = 20.34

r = roundFloatR(n, 6); // r = 20.3361
r = roundFloatR(n, 6, {return: 'string'}); // r = "20.336100"

// negative precision
r = roundFloatR(n, -2); // r = 20.3360999822617 

using a string value

let n = '20.48490002346038';

let r = roundFloatR(n); // r = 20
r = roundFloatR(n, 2); // r = 20.49

r = roundFloatR(n, 6); // r = 20.4849
r = roundFloatR(n, 6, {return: 'string'}); // r = "20.484900"

// negative precision
r = roundFloatR(n, -10); // r = 20.4849

What about performance ?
Most of the time it will convert the provided value in under .3 ms. (measured with performance.now())

What is not supported and possible issues:

  • not supported: exponential type values some changes may be required to support them.
  • possible issues:
    • a negative precision value that exceeds the provided number length or its float separator index may cause unexpected results as these cases are not handled yet.
    • no error handling in case the n parameter doesn't match what is currently asked.
Darkosphere
  • 107
  • 8
0

I think below function can help

function roundOff(value,round) {
   return (parseInt(value * (10 ** (round + 1))) - parseInt(value * (10 ** round)) * 10) > 4 ? (((parseFloat(parseInt((value + parseFloat(1 / (10 ** round))) * (10 ** round))))) / (10 ** round)) : (parseFloat(parseInt(value * (10 ** round))) / ( 10 ** round));
}

usage : roundOff(600.23458,2); will return 600.23

KRISHNA TEJA
  • 147
  • 1
  • 13
0

If you're using Browserify today, you're going to have to try: roundTo a very useful NPM lib

peterb
  • 891
  • 8
  • 7