424

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?

5
  • 51
    (6.688689​).toFixed(1); Commented Feb 26, 2012 at 13:25
  • Check this Commented Feb 26, 2012 at 13:25
  • possible duplicate of round number in JavaScript to N decimal places -- please use the search before you ask a new question. Commented Feb 26, 2012 at 13:41
  • 1
    possible duplicate of JavaScript: formatting number with exactly two decimals Commented Jul 4, 2015 at 8:05
  • 1
    @ShadowWizard is correct. However, .toFixed returns a string. Make sure to wrap the result in Number(). See accepted answer, and others. Commented Jan 1, 2019 at 21:15

21 Answers 21

708
Number((6.688689).toFixed(1)); // 6.7
Sign up to request clarification or add additional context in comments.

8 Comments

Convert a number to a string and then back again? That can't be fast.
not good if your number has less decimals than needed. It adds some
as JS benchmark show, it is slower than @fivedigit method
Number((456.1235).toFixed(3)) -> 456.123, Number((1.235).toFixed(2)) -> 1.24... Stupid JavaSript...
This might NOT DO what you expect! The result can even depend on the browser, see this question: stackoverflow.com/q/566564/2224996
|
213
var number = 6.688689;
var roundedNumber = Math.round(number * 10) / 10;

4 Comments

This doesn't always work. Take Math.round(1.005*100)/100 for example from MDN
@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.
Wrong. Math.round(1.015 * 100) / 100 returns 1.01 instead of 1.02
@MarcoMarsala Wrong. Who said that 0.5 rounds up to 1? There is no 100% correct convention and either variant is correct.
119

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"

5 Comments

This might NOT DO what you expect! The result can even depend on the browser, see this question: stackoverflow.com/q/566564/2224996
(6.688689).toFixed(); is equal to "7" not 7. Same for other examples.
This answer is misleading. for example (1).toFixed(4) returns '1.0000'
@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
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.
40
> +(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 )

6 Comments

In my opinion this is the best answer (best in term of best practice, most straightforward approach).
1e-10.toPrecision(3): "1.00e-10" - this rounds to significant digits.
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".
every scope is different, but in my scope, this helped me =) thanks
Mac Book M1 Pro all ~635ms
|
37

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

2 Comments

?? "Math.round10 is not a function"
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: npmjs.com/package/expected-round
14

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

2 Comments

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, 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.
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

1 Comment

this is similar to @fivedigit's answer. round(1.015, 2) still gives 1.01 instead of 1.02
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..

4 Comments

"If I had a dime for every time I've seen someone use FLOAT to store currency, I'd have $999.997634" -- Bill Karwin.
Wrong. Math.round(1.015 * 100) / 100
@emix So how you would store currency values?
Using ‘varchar’. 129956 would mean $1,299.56. This way you avoid floating point arithmetic issues. You simply divide the number by 100 when you want to display it to the end user.
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'})
)

Comments

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

Comments

4
const value = 6.688689
Math.round((value + Number.EPSILON) * 10) / 10
// = 6.7
// value = 6 -> 6
// value = 0.92 -> 0.9
// value = 0.95 -> 1

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 for @vitalii-ponomar. 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 if needing different decimal precisions:

const roundToPrecision = (value, decimalCount) => {
  const pow = Math.pow(10, decimalCount);
  return Math.round((value + Number.EPSILON) * pow) / pow;
};
// roundToPrecision(6.688689, 1) -> 6.7
// roundToPrecision(6.688689, 3) -> 6.689
// roundToPrecision(6.001234, 2) -> 6

Comments

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;
}

Comments

3
+((6.688689 * (1 + Number.EPSILON)).toFixed(1)); // 6.7
+((456.1235 * (1 + Number.EPSILON)).toFixed(3)); // 456.124

1 Comment

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. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
2

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

const math = require('mathjs')
math.round(3.1415926, 2) 
// result: 3.14

Comments

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 Comment

similar to some other answers, this fails for round(1.015, 2), which should give 1.02
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

3 Comments

roundToStep(1.015, 0.002) gives 1.014 . is that the correct way to use it
@gaurav5430 try roundToStep(1.015, 0.001)
Doesn't work, roundToStep(1.025, 0.01) returns 1.02 should return 1.03. The same issue as every other answer in this thread Math.round gives rounding errors with floats.
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.

Comments

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

2 Comments

Could you explain what this answer adds that hasn't already been covered by the previous answers?
similar to some other answers, this fails for round(1.015, 2), which should give 1.02
0

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

Comments

0

You can do something like this:

let example = 4.36333
console.log(Math.round(example*10)/10); // Output: 4.4

It worked really well for me.

2 Comments

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0 Unexpected behaviours with this Math.round, i really don't understand why people try to use functions like toFixed or toPrecision, where sometimes the result will be unexpected, or just won't work because of browser compatibility problems. This is the best solution, even in terms of performance, just be careful to put in a number and not a numeric string.
-3
Round: ~~(n+0.5)
Floor: ~~n
Ceil: ~~n+(n%1>0?1:0)

1 Comment

Welcome to Stack Overflow! On Stack Overflow, the how is important, but much of the site's quality level comes from people going out of their way to explain why. While a correct code-only answer get the person who asked the question past whatever hurdle they might be facing, it doesn't do them or future visitors much good in the long run. See Is there any benefit in code-only answers?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.