Precise finance in JavaScript
JavaScript knows only one number type: signed 64Bit floating point.
That is pretty cool most of the time because you can’t run into strange type conversion issues when every number is already of the exakt same type.
However, as soon as you do financial mathematics in JS, you’ll run into pretty bad mojo. Money does not have more than two decimal fractional digits and it’s always rounded before any calculation is made. So if you throw around money values in JavaScript, it will behave incorrect in terms of currency although the math is perfectly fine.
To mitigate the dangers of this problem, you can introduce a new type of number: The Money object! It’s an object made of cash, yeah!
Ok, here’s the code:
var Money = function(amount) {
if ('number' !== typeof amount) {
amount = 0;
}
this.amount = amount;
}
Money.prototype.valueOf = function() {
return Math.round(this.amount * 100) / 100;
}
The valueOf() method is called every time you try to use an object like a primitive type like Number, String or Boolean. By default it returns the string “[object Object]” if you try to do that, which is not very useful. But as you see you can override this behavior by defining a new method of the same name on the constructors prototype.
Now this happens:
var m = new Money(50.42355446); var n = new Money(30.342141); sys.puts(m.amount + n.amount); //80.76569546 sys.puts(m+n); //80.76
You can implement a more sophisticated (and maybe less customer friendly) rounding algorithm, if you like. I’m not an accountant but I’m sure there are rules how money has to be rounded in different situations.
And hey, having a constructor for Money sounds pretty awesome, right?