js-money
js-money copied to clipboard
Possibly wrong result after multiplication
Multiplying these two numbers together seems to yield the wrong result:
Money.fromDecimal(2090.50, Money.USD).multiply(Money.fromDecimal(8.61, Money.USD)).toDecimal() // = 17999.2
Should be 17999.21.
Internally I think this is what happens:
209050 * 8.61 // = 1799920.499999999.... Math.round(1799920.4999999998) // = 1799920
It tests if you passed in a rounder, if not it defaults to regular old Math.Round:
if (!isFunction(fn)) fn = Math.round;
If you add the rounder of your choice to the formula you should get what you want. For example:
Money.fromDecimal(2090.50, Money.USD).multiply(Money.fromDecimal(8.61, Money.USD),Math.ceil).toDecimal()
Result: 17999.21
The thing is, I don't want to use ceil here since every other number would also be rounded up. The issue is that 1799920.499999999.... is actually 1799920.5 in precise arithmetic, and should be round up.
Hmm perhaps someone can review and or write up some code to better handle rounding after the currency decimal place. I believe MDN had some documentation on this or maybe it was stack exchange I read about it.
At the end of the day though if financial precision is important down to the fraction of a cent it may be something that should be shifted off JS and to a language that better supports decimal values.
Maybe use something like https://github.com/MikeMcl/big.js ? I think you get most of the precision related stuff for free with a library like that.
Edit: And another bonus is that you get correct rounding for negative numbers.