Live data from Hacker News

How to Handle Monetary Values in JavaScript

frontstuff.io

81–90 of 115 posts

Re: How to Handle Monetary Values in JavaScript

#81

I wish you could add different currencies together: Dinero({amount: 5000, currency: 'USD'}) .add(Dinero({ amount: 1000, currency: 'EUR'})) ...and then convert that sum to a concrete currency later. This feature request inspired by http://blog.ploeh.dk/2017/10/16/money-monoid/

How would you deal with exchange rate, which changes in real time?

In the lazy version i have suggested, the exchange rates are deferred until you “need to know” and the sum is converted into a concrete currency.

If you’re keeping these values around in memory for an extended period of time time and you care about rapid changes to exchange rates, then you have a complex domain and the deferred exchanges may or may not be a good fit, but at that point you need larger system design, not a JavaScript library.

Also in my dream money library, division and multiplication would be done with whole number fractions like

    new Dinero({amount: 1000, currency: ‘usd’})
    .multiply({numerator: 1, denominator: 3 })
which can similarly be deferred to prevent rounding errors in partial calculations.

Re: How to Handle Monetary Values in JavaScript

#82

Maybe it’s just that I’ve done a few gigs at financial institutions, but it’s pretty shocking to see the number of people in this thread arguing that it’s a-ok to use floating point for money. I don’t want to get dragged down into specifics, but if you’re doing this, please, please don’t. Money is one of those things like dates and times - everyone who hasn’t done much of it can’t figure out what all the fuss is abou…

I'm curious to hear about your specifics, since I was at a shop where front office used all floats (doubles). Not sure what the back office did, but I doubt it was all done in arbitrary position arithmetic. Note that if an accountant says things need to be accurate down to the penny, that's probably an exaggeration [1]. Financial statements are typically rounded to the thousands, e.g. Intel's are rounded to million […

If you bill customers for anything, and there are multiple items being totaled on an invoice, you do not want that total to be anything except an accurate sum of the individual parts.

At a minimum, you look like a rinky dink operation that doesn't know how to add dollars and cents. On the other end of the spectrum, some people will likely accuse you of theft, and not nicely.

Do not fall under the assumption that the amount you mis-bill will inform how upset the people are that contact you. You will likely be the easy and obvious scapegoat for all their recent annoyances. For example, imagine all the people upset at their AT&T, Comcast or Verizon bill, who now have an easy and obvious thing to point at as an example of over billing. Have fun with those transferred emotions...

Re: How to Handle Monetary Values in JavaScript

#83
post #82

Earlier quoted context omitted.

I'm curious to hear about your specifics, since I was at a shop where front office used all floats (doubles). Not sure what the back office did, but I doubt it was all done in arbitrary position arithmetic. Note that if an accountant says things need to be accurate down to the penny, that's probably an exaggeration [1]. Financial statements are typically rounded to the thousands, e.g. Intel's are rounded to million […

If you bill customers for anything, and there are multiple items being totaled on an invoice, you do not want that total to be anything except an accurate sum of the individual parts. At a minimum, you look like a rinky dink operation that doesn't know how to add dollars and cents. On the other end of the spectrum, some people will likely accuse you of theft, and not nicely. Do not fall under the assumption that the…

I think that's the disconnect here — 'high' finance is not an exact science, and clients don't actually have an easy way of checking the numbers directly themselves — not only the models, but the inputs are also proprietary. Even auditors and regulators are dependent on bank models.

Note that the article's advice is to use their own library, but the library just uses JS floats as ints and a separate precision arg:

https://github.com/sarahdayan/dinero.js/blob/master/src/dine...

This doesn't give you any more precision than using floats directly, just a wider 'mantissa' range.

Re: How to Handle Monetary Values in JavaScript

#84
post #26

Earlier quoted context omitted.

I don't think it's true that there's no consensus around how to programatically handle monetary values. Maybe there's no consensus around how to do it in JavaScript. In the Java world, there's JSR-354: https://jcp.org/en/jsr/detail?id=354 Cobol has handled money well for decades. .NET has Decimal, which should handle money correctly as long as you're working with values less than 79.2 octillion. In my part of the wor…

Exactly correct. More stuff than most people expect is still handled by COBOL. I haven't worked with a bank in a few years, but back in 2015 the one I was at was attempting to migrate a lot of the COBOL tasks to Java.

[deleted]

Re: How to Handle Monetary Values in JavaScript

#85

Maybe it’s just that I’ve done a few gigs at financial institutions, but it’s pretty shocking to see the number of people in this thread arguing that it’s a-ok to use floating point for money. I don’t want to get dragged down into specifics, but if you’re doing this, please, please don’t. Money is one of those things like dates and times - everyone who hasn’t done much of it can’t figure out what all the fuss is abou…

finance is a different culture than hackernews, and the people speak different languages with different philosophy and assumptions about the world.

maybe this is not a technical issue, maybe its a subculture interaction issue that involves a lot of technical details.

i dont think its easy to 'understand' unless one group spends time with another, and i dont mean half an hour meeting, i mean like, shadowing someone for a week.

Re: How to Handle Monetary Values in JavaScript

#86
post #82

Earlier quoted context omitted.

If you bill customers for anything, and there are multiple items being totaled on an invoice, you do not want that total to be anything except an accurate sum of the individual parts. At a minimum, you look like a rinky dink operation that doesn't know how to add dollars and cents. On the other end of the spectrum, some people will likely accuse you of theft, and not nicely. Do not fall under the assumption that the…

I think that's the disconnect here — 'high' finance is not an exact science, and clients don't actually have an easy way of checking the numbers directly themselves — not only the models, but the inputs are also proprietary. Even auditors and regulators are dependent on bank models. Note that the article's advice is to use their own library, but the library just uses JS floats as ints and a separate precision arg: ht…

I thought it was fairly obvious I wasn't talking about banking. I was providing an example of a much more common scenario, which many businesses have to deal with, that also provides a good reason for taking care with currency.

> This doesn't give you any more precision than using floats directly, just a wider 'mantissa' range.

Floating point errors sometimes result in slightly smaller values than expected, and this can result in problems when they are passed around if even one spot if missed that needs to round. For example, some databases might truncate 1.9999999999 to 1.99 instead of round to 2.00.

As a simple illustration, consider the following Javascript (because it's easily available):

    price1 = 0.10;
    price2 = 0.20;
    package1 = price1 + price2; // Hmm, 0.30000000000000004 on my system
    ten_packages = 10*package1
    money_received = 5.00;
    change_due = money_received - ten_packages;
    // change_due is 1.9999999999999996,should be 2.00
So, either you choose floating point, and make sure to always round prior to display or passing to any other system and if you miss a spot it will probably just work fine until you hit specific values, or you convert to cents, and you only have to worry about overflow, and any place you don't convert is obvious because it's not formatted with cents and is an order of magnitude too large. And if you're worried that an int is too small and might overflow, just use a long, and that problem goes away for all conceivable real values in your lifetime.

If you're coding defensively (and we're talking about money here, so why wouldn't you be?), one of them is obviously a better choice

Re: How to Handle Monetary Values in JavaScript

#87
post #86

Earlier quoted context omitted.

I think that's the disconnect here — 'high' finance is not an exact science, and clients don't actually have an easy way of checking the numbers directly themselves — not only the models, but the inputs are also proprietary. Even auditors and regulators are dependent on bank models. Note that the article's advice is to use their own library, but the library just uses JS floats as ints and a separate precision arg: ht…

I thought it was fairly obvious I wasn't talking about banking. I was providing an example of a much more common scenario, which many businesses have to deal with, that also provides a good reason for taking care with currency. > This doesn't give you any more precision than using floats directly, just a wider 'mantissa' range. Floating point errors sometimes result in slightly smaller values than expected, and this…

> I thought it was fairly obvious I wasn't talking about banking

Right, but the article is talking about all use cases of currency... not all of which have customers that care about penny precision. I think we're in agreement that the business use case should be driving the technical requirements, and sometimes software engineers overestimate the precision actually necessary.

Overflow modes aren't always consistent between all your systems either, so I think in practice, fixnums also have issues and the advantage isn't totally clearcut.

> always round prior to display or passing to any other system

This rather depends on how much control you have over the other systems. Since, you're basically throwing away precision every time you round, it's preferable to use floats to pass data back and forth and only round before you display.

I mean in practice, you should be using formatted outputs (whether printf format strings or something fancier) to show monetary amounts, and those should be doing rounding automatically.

Re: How to Handle Monetary Values in JavaScript

#88

Earlier quoted context omitted.

How would you deal with exchange rate, which changes in real time?

In the lazy version i have suggested, the exchange rates are deferred until you “need to know” and the sum is converted into a concrete currency. If you’re keeping these values around in memory for an extended period of time time and you care about rapid changes to exchange rates, then you have a complex domain and the deferred exchanges may or may not be a good fit, but at that point you need larger system design, n…

But say the euro goes down 50% against the USD, then you are probably going to want differing amounts of those currencies right?

I think generally you 'need to know' immediately.

Re: How to Handle Monetary Values in JavaScript

#89
post #86

Earlier quoted context omitted.

I thought it was fairly obvious I wasn't talking about banking. I was providing an example of a much more common scenario, which many businesses have to deal with, that also provides a good reason for taking care with currency. > This doesn't give you any more precision than using floats directly, just a wider 'mantissa' range. Floating point errors sometimes result in slightly smaller values than expected, and this…

> I thought it was fairly obvious I wasn't talking about banking Right, but the article is talking about all use cases of currency... not all of which have customers that care about penny precision. I think we're in agreement that the business use case should be driving the technical requirements, and sometimes software engineers overestimate the precision actually necessary. Overflow modes aren't always consistent b…

> not all of which have customers that care about penny precision.

No, I think all customers care about penny precision when you are talking about money they have or owe. Either the amounts in question are small enough that a penny isn't negligible, even if it's not important, or the amounts are large enough that an error like that really shouldn't exist, because they should be taking it very seriously.

People might be willing to let it go because it's a small amount, but they'll remember it.

> Overflow modes aren't always consistent between all your systems either, so I think in practice, fixnums also have issues and the advantage isn't totally clearcut.

They're consistent in that it's generally trivial to allocate enough bits to it that an overflow can't happen in any sane inputs. As opposed to floating point, where errors happen throughout the entire range of sane inputs.

> Since, you're basically throwing away precision every time you round, it's preferable to use floats to pass data back and forth and only round before you display.

No, you're generally not throwing out precision when you round in this case. You're throwing out error. If you apply a percentage to money, they you might be throwing out precision, and that's a case you should think about. But for currencies any time you round you are purely fixing floating point errors that comes naturally by mixing number bases in this way.

> t's preferable to use floats to pass data back and forth and only round before you display.

You are explicitly saying it's preferable to use a lossy encoding for pass data back and forth because as long as you remember to do so there's a fairly easy way to recover the loss. the question remains, why is that preferably to using a medium that isn't lossy for any sane input you could want to represent?

Re: How to Handle Monetary Values in JavaScript

#90
post #82

Earlier quoted context omitted.

If you bill customers for anything, and there are multiple items being totaled on an invoice, you do not want that total to be anything except an accurate sum of the individual parts. At a minimum, you look like a rinky dink operation that doesn't know how to add dollars and cents. On the other end of the spectrum, some people will likely accuse you of theft, and not nicely. Do not fall under the assumption that the…

I think that's the disconnect here — 'high' finance is not an exact science, and clients don't actually have an easy way of checking the numbers directly themselves — not only the models, but the inputs are also proprietary. Even auditors and regulators are dependent on bank models. Note that the article's advice is to use their own library, but the library just uses JS floats as ints and a separate precision arg: ht…

I think you are right. I also worked on a bill-tracking software and one of the first things we noticed is that each company has their own way of rounding totals. There is no one correct way. For example one company rounds each line to three digits internally for the total but prints only two digits on each line.

For my software I started using decimaljs for the highest precision but in the end it never made any difference cent wise even when the payments go in the millions.

Post reply on HN