Rendered at 06:35:30 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
sieve 18 hours ago [-]
Accounting has the concept of materiality. But you still want the figures to tally to the last cent.
One way to do this is to separate the computation/storage and presentation layer: use integers to store values as cents for computation/storage and only convert to dollars+cents on display. But then someone might suddenly demand three digits after the decimal point and you cannot go about changing every stored value just because the logic changed in one part of the application. So, using decimals is the safer choice.
I prefer integers for my plain text ledger software though because the format is in my control.
nly 13 hours ago [-]
I've worked at 3 separate trading firms, each making millions or billions in profit yearly, that just use doubles for prices and cash quantities internally.
Just before you send something on the wire you just make sure you serialize (part of which is rounding) to the appropriate tick size.
Generally speaking tick sizes (cents, valid trade price increments, whatever) are many orders of magnitude greater than any possible calculation error, so rounding to the nearest tick just works
sieve 6 hours ago [-]
My concern is something fairly boring but important nevertheless: your bills/invoices, receipts, credit/debit notes, contract notes, trial balances, ledgers/statements etc.
Internally, you may use whatever precision/scale you want, and compute using doubles or decimals or integers. But I want to see 100.01 - (37.29 + 41.63) = 100.01 - 78.92 = 21.09 in all of these statements.
adrian_b 14 hours ago [-]
Using 64-bit integers as a count of a hundredth or of a thousandth part of a cent should be enough for most purposes (i.e. up to ten thousand or one hundred thousand billions of $).
If you want to be able to count trillions of trillions of dollars with a resolution of a millionth part of a cent, then you can use 128-bit integers.
Computing exactly with 128-bit integers is many times faster than computing only approximately with decimal floating-point numbers and it requires less memory storage for the same dynamic range.
fourier54 13 hours ago [-]
Actually 128 int uses 2 times the storage for less dynamic range.
I agree however that for financial applications int is always better. You don't want float dynamic range on finance calculations
PaulDavisThe1st 14 hours ago [-]
This gets tricky when it comes to dealing with currency conversion. On my most recent credit card bill, foreign currency transactions show an exchange rate with 10 digits of precision.
adrian_b 13 hours ago [-]
When implementing currency with integers, actually with fixed-point numbers, there is no difficulty in having an exchange rate with the same precision as the integer format, i.e. up to 18-19 digits for 64-bit integers.
You just have to implement the conversion function carefully, i.e. the exchange ratio would actually be represented not by a single number, but by a ratio of suitable integers, to ensure no loss of precision during the conversion done by exact multiplication with extended double-word result and then division.
hansvm 16 hours ago [-]
I like using rational types for that sort of thing.
amelius 19 hours ago [-]
> Many people know that you shouldn’t do decimal calculations, such as those involving U.S. dollars and cents, with the floating-point numbers in most programming languages. This is because decimal numbers can’t be expressed exactly as such floating-point numbers, so you will encounter rounding errors.
Why not, rounding to the nearest cent is going to be much less precise for any realistic amount of dollars when using 64 bit floats (the type of float Javascript uses in every browser).
sluukkonen 18 hours ago [-]
It’s easier just to use a proper decimal type than to remember all of the ways where using floats will bite you in the ass. The behavior is unintuitive even in trivial examples. Code like
True, but those who do not use decimal floating-point numbers do not use such binary floating-point numbers.
They use binary fixed-point numbers/integers, where such computations are exact, while not having the huge computational overhead of decimal floating-point numbers.
OGWhales 15 hours ago [-]
Indeed, though this is platform dependent. Mainframes have strong hardware support for decimal fixed-point arithmetic, making it the preferred representation for fixed-scale business data, though conceptually it's very similar to binary fixed-point.
Decimal floating-point is also hardware-supported, so it doesn’t carry the same computational overhead it does on platforms where it must be implemented in software.
adrian_b 13 hours ago [-]
For many years, nobody has supported decimal numbers in hardware, except IBM (the deprecated instructions of Intel 8086 and 8087 do not count).
IBM has done this, despite it being an inferior technical solution, because it binds those who choose it to IBM hardware.
Programming currency operations with decimal floating-point numbers is easier for naive programmers.
Even on IBM mainframes, implementing currency operations using 64-bit or 128-bit integers is much faster and less resource-consuming than with decimal numbers, but the implementation of some of the operations can be a little tricky, when it must be guaranteed that no loss of precision may occur.
I think that I might have seen recently an announcement from someone else than IBM who has introduced hardware support for decimal floating-point numbers, perhaps from Fujitsu. In any case, whoever introduces such hardware support does it to lure some customers to migrate from IBM to them, and not because it were a good solution for implementing operations with money.
OGWhales 7 hours ago [-]
[dead]
AlotOfReading 15 hours ago [-]
Decimals can bite you in the ass too. Try dividing by 3, or using transcendental functions.
Changing representations isn't a substitute for the numerical analysis you should be doing for financial calcs.
vatsachak 14 hours ago [-]
threshold = 1e-9 enters the chat
glimshe 18 hours ago [-]
The rounding behavior with true decimals is easy to control and understand across number magnitudes and doesn't suffer from platform specific quirks like floats/doubles.
The article's images clearly show the rounding error mess your get without decimals.
sobriquet9 17 hours ago [-]
There's still catastrophic cancellation, where subtracting two large numbers that are very close results in an answer with reduced precision.
amelius 18 hours ago [-]
But the rounding errors are way down in the nano-cents. Not worrying about them is cheaper!
andreareina 18 hours ago [-]
The decimal library worries about rounding, that's basically free. With floats you need to decide when to use rounding (because you don't want to show a balance of -0.000000086) and it's more difficult to use automatic checks for the same reason.
glimshe 18 hours ago [-]
If you're calculating your monthly expenses that's okay, but across millions of transactions of arbitrary amounts, something financial systems do regularly, aggregates start not adding up and you don't know where the money went.
bee_rider 16 hours ago [-]
I think there’s an implicit assumption with this sort of “use a special decimal type” advice: that the rules of the transactions are defined in terms of decimal rounding.
I mean, just as an example, your savings account interest could be computed continuously, e^(rt), which would obviously be better approximated in floating point than some decimal type. But they won’t have to do any approximation if they write the contract so that the value compounds nightly and is rounded to the nearest, whatever, tenth of a cent (which means that the rounding isn’t an approximation at all, it is part of the definition of the value being represented).
clickety_clack 14 hours ago [-]
Regular people understand the decimal system and they understand rounding in that system. The floating point system is a different system that they don't understand. People need to trust that the mechanics of payments are correct or they feel like they're being ripped off, and you can't really trust what you don't understand. Rounding of decimal pennies means that people get payments systems they can trust at the cost of precision. Nobody cares about sometimes being up or sometimes being down a fraction of a penny.
knorker 18 hours ago [-]
"The nearest cent" is already a bad assumption. Should IEEE 754 representation dictate taxes and money splitting?
You could end up with splitting an account down the middle, and ending up with an extra cent being created out of thin air, or one destroyed. In billions of transactions each day, this could be a problem for balancing books when there is no longer any equality check.
When not using floats, the rules and checks become more… deterministic, if you don't mind stretching the definition of that word a bit.
kphorn 13 hours ago [-]
Great blog post by Peter Gibbons, Michael Bolton, and Samir "Nagana-work-here-anymore" about their time at Initech
"all right so when the subroutine compounds the interest, it uses all of these extra decimal places that just get rounded off. So we simplified the whole thing, we round them all down and drop the remainder... in to an account that we opened"
sobriquet9 17 hours ago [-]
Besides Python’s fractions, there are also constructive reals, exemplified by Android calculator where you can swipe any answer to get as many digits as you want.
krige 18 hours ago [-]
Possibly the first case I've encountered where image loaded before the text. A grid of 1px rectangles? How unsettling.
jgalt212 17 hours ago [-]
> Many people know that you shouldn’t do decimal calculations, such as those involving U.S. dollars and cents, with the floating-point numbers in most programming languages. This is because decimal numbers can’t be expressed exactly as such floating-point numbers, so you will encounter rounding errors.
Decimals or pennies, you still have rounding errors. For example, if your contract is $100 / year. You will get the full $100 if you bill yearly, quarterly, or semi-annually. But if you bill monthly, no matter if you deal in pennies or fractional dollars, the sum total of your invoices for the year will be less than $100.
nitwit005 9 hours ago [-]
Usually the contract itself specifies how that should work. You often see a schedule of payments, and how dealing with early cancelation should work.
gottheUIblues 17 hours ago [-]
Bill 8 months at $8.33 and 4 months at $8.34?
astrobe_ 14 hours ago [-]
If you're going for ad hoc solution to that specific problem, just charge $99/year or $102/year instead, depending on how you feel like about profit margins.
jgalt212 15 hours ago [-]
Yeah, I know there's more than one way to skin a cat. My point is that storing all accounting values in pennies is overrated.
mytailorisrich 16 hours ago [-]
Having 11 equal payments and a 1st or 12th one of a different amount to make the total exact is a fairly common way of dealing with this.
One way to do this is to separate the computation/storage and presentation layer: use integers to store values as cents for computation/storage and only convert to dollars+cents on display. But then someone might suddenly demand three digits after the decimal point and you cannot go about changing every stored value just because the logic changed in one part of the application. So, using decimals is the safer choice.
I prefer integers for my plain text ledger software though because the format is in my control.
Just before you send something on the wire you just make sure you serialize (part of which is rounding) to the appropriate tick size.
Generally speaking tick sizes (cents, valid trade price increments, whatever) are many orders of magnitude greater than any possible calculation error, so rounding to the nearest tick just works
Internally, you may use whatever precision/scale you want, and compute using doubles or decimals or integers. But I want to see 100.01 - (37.29 + 41.63) = 100.01 - 78.92 = 21.09 in all of these statements.
If you want to be able to count trillions of trillions of dollars with a resolution of a millionth part of a cent, then you can use 128-bit integers.
Computing exactly with 128-bit integers is many times faster than computing only approximately with decimal floating-point numbers and it requires less memory storage for the same dynamic range.
You just have to implement the conversion function carefully, i.e. the exchange ratio would actually be represented not by a single number, but by a ratio of suitable integers, to ensure no loss of precision during the conversion done by exact multiplication with extended double-word result and then division.
Why not, rounding to the nearest cent is going to be much less precise for any realistic amount of dollars when using 64 bit floats (the type of float Javascript uses in every browser).
They use binary fixed-point numbers/integers, where such computations are exact, while not having the huge computational overhead of decimal floating-point numbers.
Decimal floating-point is also hardware-supported, so it doesn’t carry the same computational overhead it does on platforms where it must be implemented in software.
IBM has done this, despite it being an inferior technical solution, because it binds those who choose it to IBM hardware.
Programming currency operations with decimal floating-point numbers is easier for naive programmers.
Even on IBM mainframes, implementing currency operations using 64-bit or 128-bit integers is much faster and less resource-consuming than with decimal numbers, but the implementation of some of the operations can be a little tricky, when it must be guaranteed that no loss of precision may occur.
I think that I might have seen recently an announcement from someone else than IBM who has introduced hardware support for decimal floating-point numbers, perhaps from Fujitsu. In any case, whoever introduces such hardware support does it to lure some customers to migrate from IBM to them, and not because it were a good solution for implementing operations with money.
Changing representations isn't a substitute for the numerical analysis you should be doing for financial calcs.
The article's images clearly show the rounding error mess your get without decimals.
I mean, just as an example, your savings account interest could be computed continuously, e^(rt), which would obviously be better approximated in floating point than some decimal type. But they won’t have to do any approximation if they write the contract so that the value compounds nightly and is rounded to the nearest, whatever, tenth of a cent (which means that the rounding isn’t an approximation at all, it is part of the definition of the value being represented).
You could end up with splitting an account down the middle, and ending up with an extra cent being created out of thin air, or one destroyed. In billions of transactions each day, this could be a problem for balancing books when there is no longer any equality check.
When not using floats, the rules and checks become more… deterministic, if you don't mind stretching the definition of that word a bit.
https://www.youtube.com/watch?v=yZjCQ3T5yXo
"all right so when the subroutine compounds the interest, it uses all of these extra decimal places that just get rounded off. So we simplified the whole thing, we round them all down and drop the remainder... in to an account that we opened"
Decimals or pennies, you still have rounding errors. For example, if your contract is $100 / year. You will get the full $100 if you bill yearly, quarterly, or semi-annually. But if you bill monthly, no matter if you deal in pennies or fractional dollars, the sum total of your invoices for the year will be less than $100.