public-transport / friendly-public-transport-format

A format for APIs, libraries and datasets containing and working with public transport data.
Creative Commons Attribution Share Alike 4.0 International
125 stars 1 forks source link

type of `price.amount` value #24

Closed kiliankoe closed 7 years ago

kiliankoe commented 7 years ago

A very minor pet peeve of mine is the storing of money values in floating point numbers, since this almost always leads to inconsistencies at some point or another due to the fact that floats misrepresent certain values. It is however a lot more user-friendly to use them, since 4.95 is obviously easier understood than 495 (or just define everything as being cent values). Most bigger currency libraries actually use integers instead to prevent possible issues.

I'm not necessarily proposing a change, just want to have mentioned/discussed it.

derhuerst commented 7 years ago

Yup, in basically every language there are libs for handling arbitrary-precision math to prevent floating point errors. They have methods to get a plain value from a computation. In JS, often as strings are used.

I think using integers instead of floats is inherently error-prone, as I might easily interpret 123 as 123€, especially if I don't know the currency. I'm therefore in favour of using something else, like strings or arrays ([1, 23]).

kiliankoe commented 7 years ago

Strings or arrays make it even weirder and more error-prone imo. Numeric types are well defined, strings or arrays could possibly contain all kinds of corrupted or odd data.

derhuerst commented 7 years ago

In which way? JSON parsing won't be done manually, right?

Imagine you have a value of 450 and IDR as currency. Both 450 IDR and 4.5 IDR Indian Rupees are a reasonable price for Indian trains (for very different distances of course). I think it would be very misleading to just store 4.5 IDR as 450, especially if you as a programmer don't know local city names.

Yes, floating point arithmetic can mess prices up, but think about what people will do.

kiliankoe commented 7 years ago

If by manually you mean without the help of an FPTF library, I think it very well might be. If this project is successful in its mission quite a few people might be consuming this data. All it takes is one provider/etc messing up and writing 3.50€ (or even 3,50) as a string value, which would and probably should lead to undefined behavior. Or arrays with zero or three or more values.

Having JSON's "typesystem" preventing at least those errors is a plus in my opinion. You're definitely right though about different currencies making this problem a bit harder to deal with. I'll propose either adding a field for a multiplier (or similar) which could clear up misconceptions by specifying 100 for EUR for example or just sticking with floats to keep everything simple and accessible.

Unfortunately having a numeric value in JSON is either an integer or a float, so the integer method wouldn't lead to more safety than described above with strings and arrays. Therefore my vote goes to sticking with the previous design instead of overcomplicating stuff.

derhuerst commented 7 years ago

As I said: AFAIK, floating point mechanics are not relevant when creating a float from a string, only when doing calculations with floats. Therefore it shouldn't be a problem, which is why I'm in favour of plain JSON numbers as well (if I understood you correctly).

We might put a small link to a page explaining floating point errors to those unaware of it. Maybe there's a nice page someone already created.

juliuste commented 7 years ago

I know very little about issues like this, therefore I'll abstain from this discussion.

kiliankoe commented 7 years ago

As discussed here and elsewhere, it makes sense to keep the current format 👍