598

Can you round a number in JavaScript to one character after the decimal point (properly rounded)?

I tried the *10, round, /10, but it leaves two decimals at the end of the int.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Walker
  • 128,495
  • 27
  • 68
  • 94

25 Answers25

1082

Math.round(num * 10) / 10 works, and here is an example...

var number = 12.3456789
var rounded = Math.round(number * 10) / 10
// rounded is 12.3

If you want it to have one decimal place, even when that would be a 0, then add...

var fixed = rounded.toFixed(1)
// 'fixed' is always to one decimal point
// NOTE: .toFixed() returns a string!

// To convert back to number format
parseFloat(number.toFixed(2))
// 12.34
// but that will not retain any trailing zeros

// So, just make sure it is the last step before output,
// and use a number format during calculations!

Using this principle, for reference, here is a handy little round function that takes precision...

function round(value, precision) {
    var multiplier = Math.pow(10, precision || 0);
    return Math.round(value * multiplier) / multiplier;
}

... usage ...

round(12345.6789, 2) // 12345.68
round(12345.6789, 1) // 12345.7

... defaults to round to nearest whole number (precision 0) ...

round(12345.6789) // 12346

... and can be used to round to nearest 10 or 100, etc...

round(12345.6789, -1) // 12350
round(12345.6789, -2) // 12300

... and correct handling of negative numbers ...

round(-123.45, 1) // -123.4
round(123.45, 1) // 123.5

... and can be combined with toFixed to format consistently as string ...

round(456.7, 2).toFixed(2) // "456.70"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Billy Moon
  • 57,113
  • 24
  • 136
  • 237
  • 68
    Be careful using `.toFixed()` as it returns a string when you maybe want a number. – Cobby Sep 14 '12 at 05:25
  • 1
    Cool, obviously using `parseFloat` will remove decimals left by `.toFixed()` if it's a whole number (zeros). Generally, if you want to do the math it's best to follow your first example. If you want to display a number in your UI then use `.toFixed()`. – Cobby Sep 17 '12 at 01:12
  • Hmmm... that makes sense, any way you convert to number must always strip the erroneous zeros, which is why it has to stay a string. I guess it should always be the last step before display, and not used in calculations. – Billy Moon Sep 17 '12 at 10:22
  • 3
    Be careful using `.toFixed()` as it might return different rounding results for different browsers. Read [**this post**](http://stackoverflow.com/questions/566564/javascript-functions-math-roundnum-vs-num-tofixed0-and-browser-inconsistenci) for details on the topic! – Wilt Mar 04 '14 at 13:02
  • 1
    Can I add a zero if no DP are present? – Nick Nov 24 '16 at 12:34
160
var number = 123.456;

console.log(number.toFixed(1)); // should round to 123.5
Pablo Fernandez
  • 103,170
  • 56
  • 192
  • 232
  • 6
    Sometimes `toFixed()` has glitches - I have seen it in a Chrome browser where I call `toFixed()`, then convert to a string, and it shows something like `10.00000000068` - weird. Cannot reproduce this reliably though. – Hamish Grubijan Apr 25 '13 at 21:45
  • Yes, I accountered glitches with toFixed() even with just few decimals. It rounded fraction 4 to the next higher number instead of lower, if I recall correctly. – Dalibor Jun 30 '15 at 07:43
  • 3
    as mentioned by @cobby above: _be careful using `.toFixed()` as it returns a `String` when you maybe want a `Number`_ – Ricardo May 25 '19 at 00:41
54

If you use Math.round(5.01) you will get 5 instead of 5.0.

If you use toFixed you run into rounding issues.

If you want the best of both worlds, combine the two:

(Math.round(5.01 * 10) / 10).toFixed(1)

You might want to create a function for this:

function roundedToFixed(input, digits){
  var rounder = Math.pow(10, digits);
  return (Math.round(input * rounder) / rounder).toFixed(digits);
}
Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102
43

Lodash has a round method:

_.round(4.006);
// => 4

_.round(4.006, 2);
// => 4.01

_.round(4060, -2);
// => 4100

Documentation.

Source.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kevinleary.net
  • 8,851
  • 3
  • 54
  • 46
  • this is the best answer, but here I rewrote the lodash function function precisionRound(number, precision) { number = Number(number); if (precision) { // Shift with exponential notation to avoid floating-point issues. let pair = (number.toString() + 'e').split('e'); let value = Math.round(pair[0] + 'e' + (Number(pair[1]) + precision)); pair = (value.toString() + 'e').split('e'); return Number(pair[0] + 'e' + (Number(pair[1]) - precision)); } return Math.round(number); } – Theo Sep 14 '22 at 00:53
16

You can simply do the following:

let n = 1.25
let result = Number(n).toFixed(1)
// output string: 1.3
Rusty
  • 4,138
  • 3
  • 37
  • 45
12

I vote for toFixed(), but, for the record, here's another way that uses bit shifting to cast the number to an int. So, it always rounds towards zero (down for positive numbers, up for negatives).

var rounded = ((num * 10) << 0) * 0.1;

But hey, since there aren't any function calls, it's wicked fast. :)

And here's one that uses string matching:

var rounded = (num + '').replace(/(^.*?\d+)(\.\d)?.*/, '$1$2');

I don't recommend using the string variant, just saying.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jimbo
  • 11,004
  • 6
  • 29
  • 46
8

Try with this:

var original = 28.453

// 1.- round "original" to two decimals
var result = Math.round (original * 100) / 100  // Returns 28.45

// 2.- round "original" to 1 decimal
var result = Math.round (original * 10) / 10  // Returns 28.5

// 3.- round 8.111111 to 3 decimals
var result = Math.round (8.111111 * 1000) / 1000  // Returns 8.111

It is less complicated and easier to implement...

With this, you can create a function to do:

function RoundAndFix (n, d) {
    var m = Math.pow (10, d);
    return Math.round (n * m) / m;
}

function RoundAndFix (n, d) {
    var m = Math.pow (10, d);
    return Math.round (n * m) / m;
}
console.log (RoundAndFix(8.111111, 3));

See How to round using ROUND HALF UP. Rounding mode that most of us were taught in grade school.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
atiruz
  • 2,782
  • 27
  • 36
7

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

Naive implementation

Using the following function with halfway numbers, you will get either the upper rounded value as expected, or the lower rounded value sometimes depending on the input.

This inconsistency in rounding may introduce hard to detect bugs in the client code.

function naiveRound(num, decimalPlaces) {
    var p = Math.pow(10, decimalPlaces);
    return Math.round(num * p) / p;
}

console.log( naiveRound(1.245, 2) );  // 1.25 correct (rounded as expected)
console.log( naiveRound(1.255, 2) );  // 1.25 incorrect (should be 1.26)

Better implementations

By converting the number to a string in the exponential notation, positive numbers are rounded as expected. But, be aware that negative numbers round differently than positive numbers.

In fact, it performs what is basically equivalent to "round half up" as the rule, you will see that round(-1.005, 2) evaluates to -1 even though round(1.005, 2) evaluates to 1.01. The lodash _.round method uses this technique.

/**
 * Round half up ('round half towards positive infinity')
 * Uses exponential notation to avoid floating-point issues.
 * Negative numbers round differently than positive numbers.
 */
function round(num, decimalPlaces) {
    num = Math.round(num + "e" + decimalPlaces);
    return Number(num + "e" + -decimalPlaces);
}

// test rounding of half
console.log( round(0.5, 0) );  // 1
console.log( round(-0.5, 0) ); // 0

// testing edge cases
console.log( round(1.005, 2) );   // 1.01
console.log( round(2.175, 2) );   // 2.18
console.log( round(5.015, 2) );   // 5.02

console.log( round(-1.005, 2) );  // -1
console.log( round(-2.175, 2) );  // -2.17
console.log( round(-5.015, 2) );  // -5.01

If you want the usual behavior when rounding negative numbers, you would need to convert negative numbers to positive before calling Math.round(), and then convert them back to negative numbers before returning.

// Round half away from zero
function round(num, decimalPlaces) {
    num = Math.round(Math.abs(num) + "e" + decimalPlaces) * Math.sign(num);
    return Number(num + "e" + -decimalPlaces);
}

There is a different purely mathematical technique to perform round-to-nearest (using "round half away from zero"), in which epsilon correction is applied before calling the rounding function.

Simply, we add the smallest possible float value (= 1.0 ulp; unit in the last place) to the number before rounding. This moves to the next representable value after the number, away from zero.

/**
 * Round half away from zero ('commercial' rounding)
 * Uses correction to offset floating-point inaccuracies.
 * Works symmetrically for positive and negative numbers.
 */
function round(num, decimalPlaces) {
    var p = Math.pow(10, decimalPlaces);
    var e = Number.EPSILON * num * p;
    return Math.round((num * p) + e) / p;
}

// test rounding of half
console.log( round(0.5, 0) );  // 1
console.log( round(-0.5, 0) ); // -1

// testing edge cases
console.log( round(1.005, 2) );  // 1.01
console.log( round(2.175, 2) );  // 2.18
console.log( round(5.015, 2) );  // 5.02

console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02

This is needed to offset the implicit round-off error that may occur during encoding of decimal numbers, particularly those having "5" in the last decimal position, like 1.005, 2.675 and 16.235. Actually, 1.005 in decimal system is encoded to 1.0049999999999999 in 64-bit binary float; while, 1234567.005 in decimal system is encoded to 1234567.0049999998882413 in 64-bit binary float.

It is worth noting that the maximum binary round-off error is dependent upon (1) the magnitude of the number and (2) the relative machine epsilon (2^-52).

Amr Ali
  • 3,020
  • 1
  • 16
  • 11
7

Why not just

let myNumber = 213.27321;
+myNumber.toFixed(1); // => 213.3
  1. toFixed: returns a string representing the given number using fixed-point notation.
  2. Unary plus (+): The unary plus operator precedes its operand and evaluates to its operand but attempts to convert it into a number, if it isn't already.
goulashsoup
  • 2,639
  • 2
  • 34
  • 60
6
var num = 34.7654;

num = Math.round(num * 10) / 10;

console.log(num); // Logs: 34.8
Joseph Silber
  • 214,931
  • 59
  • 362
  • 292
5

Using toPrecision method:

var a = 1.2345
a.toPrecision(2)

// result "1.2"
E.Z.
  • 51
  • 1
  • 4
4

To complete Billy Moon's answer:

var round = function ( number, precision )
{
    precision = precision || 0;
    return parseFloat( parseFloat( number ).toFixed( precision ) );
}

The input parameter number may "not" always be a number, in this case .toFixed does not exist.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
klodoma
  • 4,181
  • 1
  • 31
  • 42
3

ES 6 Version of Accepted Answer:

function round(value, precision) {
    const multiplier = 10 ** (precision || 0);
    return Math.round(value * multiplier) / multiplier;
}
Koustav Ray
  • 1,112
  • 13
  • 26
2

I made one that returns number type and also places decimals only if are needed (no 0 padding).

Examples:

roundWithMaxPrecision(11.234, 2); //11.23
roundWithMaxPrecision(11.234, 1); //11.2
roundWithMaxPrecision(11.234, 4); //11.23
roundWithMaxPrecision(11.234, -1); //10

roundWithMaxPrecision(4.2, 2); //4.2
roundWithMaxPrecision(4.88, 1); //4.9

The code:

function roundWithMaxPrecision (n, precision) {
    const precisionWithPow10 = Math.pow(10, precision);
    return Math.round(n * precisionWithPow10) / precisionWithPow10;
}
Alberto
  • 1,423
  • 18
  • 32
2

You could accomplish the rounding off task as:

var value = Math.round(234.567*100)/100

Will give you 234.56.

Similarly

 var value = Math.round(234.567*10)/10

Will give 234.5.

In this way, you can use a variable in the place of the constant as used above.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jagbandhuster
  • 677
  • 2
  • 7
  • 20
1

A little Angular filter:

angular.module('filters').filter('decimalPlace', function() {
    return function(num, precision) {
        var multiplier = Math.pow(10, precision || 0);
        return Math.round(num * multiplier) / multiplier;
    };
});

Use it via:

{{model.value| decimalPlace}}
{{model.value| decimalPlace:1}}
{{model.value| decimalPlace:2}}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sidonaldson
  • 24,431
  • 10
  • 56
  • 61
0

This seems to work reliably across anything I throw at it:

function round(val, multiplesOf) {
  var s = 1 / multiplesOf;
  var res = Math.ceil(val*s)/s;
  res = res < val ? res + multiplesOf: res;
  var afterZero = multiplesOf.toString().split(".")[1];
  return parseFloat(res.toFixed(afterZero ? afterZero.length : 0));
}

It rounds up, so you may need to modify it according to use case. This should work:

console.log(round(10.01, 1)); //outputs 11
console.log(round(10.01, 0.1)); //outputs 10.1
Ege Özcan
  • 13,971
  • 2
  • 30
  • 51
  • What about 100.65, 50.55, 100.05, 50.05, 1.005, and 1.05? – Peter Mortensen Apr 19 '23 at 09:47
  • oh my... this is from more than 8 years ago and it seems I had implemented something spectacularly hacky, ouch. it does seem to work for the inputs you provided, not sure if you had any problems but I'd encourage anyone to use some other solution from here :) converting to string and splitting may not perform well when done in a hot loop – Ege Özcan Apr 20 '23 at 12:36
0

If you care about proper rounding up then:

function roundNumericStrings(str , numOfDecPlacesRequired){ 
     var roundFactor = Math.pow(10, numOfDecPlacesRequired);  
     return (Math.round(parseFloat(str)*roundFactor)/roundFactor).toString();  }

Else if you don't then you already have a reply from previous posts

str.slice(0, -1)
jsNovice
  • 646
  • 7
  • 12
0

Math.round( num * 10) / 10 doesn't work.

For example, 1455581777.8-145558160.4 gives you 1310023617.3999999.

So only use num.toFixed(1)

userlond
  • 3,632
  • 2
  • 36
  • 53
P.W
  • 11
0

I found a way to avoid the precision problems:

function badRound (num, precision) {
    const x = 10 ** precision;
    return Math.round(num * x) / x
}
// badRound(1.005, 2) --> 1

function round (num, precision) {
    const x = 10 ** (precision + 1);
    const y = 10 ** precision;
    return Math.round(Math.round(num * x) / 10) / y
}
// round(1.005, 2) --> 1.01
0
Math.round( mul/count * 10 ) / 10

Math.round(Math.sqrt(sqD/y) * 10 ) / 10

Thanks

roy neo
  • 1
  • 1
0
function rnd(v,n=2) {
    return Math.round((v+Number.EPSILON)*Math.pow(10,n))/Math.pow(10,n)
}

this one catch the corner cases well

penduDev
  • 4,743
  • 35
  • 37
0

If your source code is typescript you could use a function like this:

public static ToFixedRounded(decimalNumber: number, fractionDigits: number): number {
    var rounded = Math.pow(10, fractionDigits);
    return (Math.round(decimalNumber * rounded) / rounded).toFixed(fractionDigits) as unknown as number;
}
Peppe426
  • 99
  • 6
0

Using the Number constructor, we can solve this problem: For Example :

const convertToCelsius = function(element) {
    return Number(((element -32 )/ 1.8 ).toFixed(1)) ;
};

This returns a number which was converted into a string due to toFixed method, then again converted to number via number() constructor.

ahuemmer
  • 1,653
  • 9
  • 22
  • 29
-1
const solds = 136780000000; 
const number = (solds >= 1000000000 && solds < 1000000000000) ? { divisor: 1000000000, postfix: "B" }: (solds >= 1000000 && solds < 1000000000) ? { divisor: 1000000, postfix: "M" }: (solds >= 1000 && solds < 1000000) ? { divisor: 1000, postfix: "K" }: { divisor: 1, postfix: null }; 
const floor = Math.floor(solds / number.divisor).toLocaleString(); 
const firstDecimalIndex = solds.toLocaleString().charAt(floor.length+1); 
const final =firstDecimalIndex.match("0")? floor + number.postfix: floor + "." + firstDecimalIndex + number.postfix; 
console.log(final);

136780000000 --> 136.7B

1367800 --> 1.3M

1342 --> 1.3K