How do I round a JavaScript number to 2 decimal places?

36.99300003051758 I'm receiving
this kind of value how can round of this

I assume you are using JavaScript, if so this will round up or down to the nearest INTEGER.

So in the particular case you posted, the result is 37. Is that what you wanted?
round

1 Like

thank you round of working suppose i want to see only 3 digits means 39.9 what I do

Try this in a 'function' node.

msg.payload = Math.round((msg.payload) * 100) / 100;

Gives 36.99 from your posted value.

round

Here's a link to some examples.

thanks lot its working fine

Can I suggest you edit the title of your post to something like...

How to round a JavaScript number to 2 decimal places.

As 'Function node opto 22' would mean nothing to people searching the forum.

1 Like

It seems like Math.round() is a better solution, but it is not! In some cases it will NOT round correctly. Also, toFixed() will NOT round correctly in some cases.

To correct the rounding problem with the previous Math.round() and toFixed(), you can define a custom JavaScript round function that performs a "nearly equal" test to determine whether a fractional value is sufficiently close to a midpoint value to be subject to midpoint rounding. The following function return the value of the given number rounded to the nearest integer accurately.

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

var num = 9.7654;
console.log( num.roundTo(2)); //output 9.77

Can you give an example of where they give a false value?

var num = 9.7654;
msg.payload = num.toFixed(2)
return msg;

returns 9.77 as expected.

1 Like

Indeed, I'd be interested too:

let n = 1.044444444444444444444444444444444444444444444444444444444445

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

return {payload: 
    [n.toFixed(2), Math.round(n * 100) / 100, n.roundTo(2)]
}

image

PS: Adding to builtin JS object prototypes is a definite antipattern and should be avoided. It can lead to some virtually impossible to track bugs.

When they fail (without touching the exponential)

let addFailures = 0, multFailures = 0
let n = 1000000000000.1;
let a,b

for (let index = 0; index < 10000; index++) {
    n += 1000000000.01
    a = parseFloat(n.toFixed(2))
    b = Math.round(n * 100) / 100
   
    if(a !== b){
        addFailures ++;
        node.send({
            payload:{
                'operation':'add',
                'index':index,
                'number':n,
                'floatFromFixed':a,
                'Math.Round':b
            }
        })
    }    
}

n = 1.99999;

for (let index = 0; index < 10000; index++) {
    n *= 1.003
    a = parseFloat(n.toFixed(2))
    b = Math.round(n * 100) / 100   
    if (a !== b) {
        multFailures++;
        node.send({
            payload: {
                'operation': 'mult',
                'index': index,
                'number': n,
                'floatFromFixed': a,
                'Math.Round': b
            }
        })
    }
}

return {payload:'add: '+addFailures+ ' mult: '+multFailures}

Arguably that is not due to those functions failing, it is due to the basic arithmetic failing when working at the limit of the number of bits available for the calculations. Consider this for example (taking one of the failures found)

msg.payload = 10292000000091.135
msg.payload = msg.payload + 0.001
return msg;

which returns 10292000000091.137

1 Like

Ah yes, I'd forgotten about that.

In general and for most cases not really an issue. If you really need precision I'd normally use something like royNiladri/js-big-decimal: Work with large numbers on the client side with high precision. (github.com) - or indeed avoid JS all together and use Python, R or even Fortran(!) which have more mature designs for high-precision number handling.

And as always, only ever round when about to display.

// where Math.round() fails
var num = 1511000000005.2148; // this should round to 1511000000005.21
console.log(num.toFixed(2)); // outputs 1511000000005.21 ✅
console.log(num.roundTo(2)); // outputs 1511000000005.21 ✅
console.log(Math.round(num * 100) / 100); // outputs 1511000000005.22 ❌

// where toFixed() fails
num = 330349199868.985 // this should round to 330349199868.99
console.log(num.toFixed(2)); // outputs 330349199868.98 ❌
console.log(num.roundTo(2)); // outputs 330349199868.99 ✅
console.log(Math.round(num * 100) / 100); // 330349199868.98 ✅

In JSONata
$formatNumber(12.225, '0.00')
Can get '12.23'

$number($formatNumber(12.225, '0.00'))
Can get 12.23

In Function
var num = 12.225;
num.toFixed(2);
Can get '12.22'

I am sure that I was taught at school that should be 1511000000005.215 and therefore 1511000000005.22? Of course, that was over 44 years ago so maybe the accepted wisdom has changed? :smiley:

n.2148 is less than n.2150 so should round down to n.21. n.2150 and above should round to n.22.

1 Like

I think it depends on weither you round each digit by it self, or all at the same time, i.e
do you round 5.2148 to two decimal points by rounding
5.2148 which would get 5.215 and
5.215 which would become 5.22
or do you round 5.2148 by rounding the '48' so
5.2148 would be rounded down so you get 5.21

Well, we are doubtless well off-topic now :smiley:

But I vaguely remember rounding right to left.

Julian rounding is always done by the digit to the right of the one you are rounding. If it is between 0 and 4 you round down if it is five or above you round up. That's all the rules there are.

It should be done in one go. The idea of rounding is to find the value with the appropriate decimal places that is nearest to the actual value. 5.21 is nearer to 5.2148 (0.0048 away) than is 5.22 (0.0052 away), so 5.21 is the correct rounded value.