Javascript toFixed, Math.round

I am trying to calculate percentage fees for dollar amount. I have tried many ways but the rounding seems off. Is there a standard or best practice for calculating fees?

fee = 2.25 // %
total = 2

sFee = parseFloat(((fee / 100) * total).toFixed(2));
console.log(sFee)
// sFee is $0.04, should be $0.05

fee = 2.25 // %
total = 10

const x = (fee / 100) * total;
pFee = Math.round(x * 100) / 100;
console.log(pFee)

// this works with most numbers but when total is 10
// pFee is $0.22, should be $0.23

fee = 2.25 // %
total = 2

sFee = parseFloat(((fee / 100) * total + 0.00000000001).toFixed(2));
console.log(sFee)
// sFee is $0.05, 
// this seems to work best, not sure if it is the best solution.

Answer

The floating point representation has its limits, and so not all (intermediate) results are 100% accurate. See Is floating point math broken?.

To avoid this from happening, make all calculations with integers, turning any fractional inputs to integers first, and only at the very end of the calculation, turn back to fractional numbers and perform the rounding.

With that approach your example would look like this:

var fee = 2.25
var total = 10

const pFee = Math.round((fee * 100) * total / 100) / 100;
console.log(pFee); // 0.23

So the clue here is to start with fee * 100 in order to get rid of the fractional part before doing anything else.

This way of working also can be brought to its knees, but you’ll have to use some extreme numbers to make that happen.