[HN Gopher] 64-bit bank balances 'ought to be enough for anybody'?
___________________________________________________________________
64-bit bank balances 'ought to be enough for anybody'?
Author : todsacerdoti
Score : 217 points
Date : 2023-09-19 12:14 UTC (10 hours ago)
(HTM) web link (tigerbeetle.com)
(TXT) w3m dump (tigerbeetle.com)
| olalonde wrote:
| Still not enough for storing Ethereum/ERC20 balances (256-bit)...
| :(
| Shrezzing wrote:
| The hyperinflation example is quite interesting because:
|
| 1) If it happens, it happens rapidly, and you don't want to
| implement this in a hurry
|
| 2) If it happens, the global economy could well be melting down,
| and your financial institution will have other priorities to
| attend to
|
| 3) Retaining existing staff, and hiring new engineers, will be
| challenging at best
|
| You really don't want to be implementing this change in those
| circumstances.
| themagician wrote:
| By the time this is a problem the currency has collapsed and no
| one is using it anymore.
| runeks wrote:
| I think it's the worst example. I very much doubt we will ever
| see the price of, say, a car approach a billion billion dollars
| (or cents). It's too many zeros for people to work with on a
| daily basis. I think what will happen is that, at regular
| intervals, the old hyper-inflated currency will be replaced
| with a new currency that's, say, 2^32 times less than the
| original one.
|
| Besides, if you think a billion billions might be reached (64
| bits) then why wouldn't a billion billion billion billions also
| be reached (128 bits)? 128 bits seems just as arbitrary as 64
| bits in this context.
| jefftk wrote:
| Before 2009 would you have predicted that a 100 Trillion
| Dollar bill would never be issued by a central bank?
| ilyt wrote:
| 2^63 / 100 Trillion = 9.2E6 so even in this case you have
| few decimal positions left.
| zarzavat wrote:
| You may be overlooking the potential for someone to own
| more than one of those $100T bills. Apparently it was
| worth about 30 USD at the time.
| hot_gril wrote:
| If $100T = 30 USD, then probably nobody will mind if we
| round to the nearest $1B. Just like how I have no way to
| compensate someone for less than 0.01 USD.
| RandomLensman wrote:
| Germany had notes and stamps in the trillions Marks in 1924
| - nothing new there
| cesarb wrote:
| > It's too many zeros for people to work with on a daily
| basis. I think what will happen is that, at regular
| intervals, the old hyper-inflated currency will be replaced
| with a new currency that's, say, 2^32 times less than the
| original one.
|
| I lived through hyperinflation (in Brazil). What happened was
| that, at regular intervals, the old hyper-inflated currency
| was replaced with a new currency that's 10^3 times less than
| the original one. Cutting decimal zeros is better for humans,
| and three is convenient because it matches the usual three-
| digit grouping (that is, 123.450,00 becomes 123,45). This had
| to be done because, otherwise, calculators would become
| useless (most common pocket calculators had only eight
| digits).
| halosghost wrote:
| A reminder that this still isn't the correct way of handling
| money. The correct way is to put it in the type-system [1].
|
| All the best,
|
| -HG
|
| [1]
| https://web.archive.org/web/20211014094900/https://ren.zone/...
| runeks wrote:
| This only puts currency codes in the type system; and uses
| rational numbers for amounts.
|
| This is definitely useful because you can have the type system
| tell you if you've implemented e.g. exchange rate conversion
| incorrectly. But it's also a hassle because you need to reify
| currency values discovered at runtime as types, which isn't
| pretty [1].
|
| [1] https://github.com/runeksvendsen/order-
| graph/blob/eef0006cba...
| jorangreef wrote:
| Yes, and to your first point, TigerBeetle also supports
| multiple ledgers, explicitly where each ledger is for a
| separate unit or currency (with isolation enforced by
| TigerBeetle across different units/currencies).
|
| Thus, TigerBeetle doesn't preclude the use of money types at
| a higher layer (you would have seen that we tried to
| emphasize this also in the post).
|
| Another way to think of this, is that we focus on the storage
| of accounting information by providing high-performance
| accounting primitives (e.g. execute 8k double entry
| transactions all within 5ms in a single network roundtrip DB
| query).
|
| But the _accounting policy_ (rounding etc.) remains the
| responsibility of the application /organization, since this
| may differ according to requirements/jurisdiction.
| xhkkffbf wrote:
| And the Fed says, "Hold my beer!"
| keepamovin wrote:
| Reserve Bank of Zimbabwe "100 Trillion Dollars" hahahahaha
|
| LOL. Is that real? OMG, that's incredible. Image if this trend
| kept going: what sign of humanity that new SI units need to be
| minted first because inflation drives currencies to insane new
| denominations, rather than cat videos, IoT and porn bulge
| yottabytes out of bounds?
| ceejayoz wrote:
| Zimbabwe underwent a period of hyperinflation.
|
| https://en.wikipedia.org/wiki/Hyperinflation_in_Zimbabwe
|
| They eventually stopped printing currency.
| hot_gril wrote:
| > For the same reason, digital currencies are another use case
| for 128-bit balances, where again, the smallest quantity of money
| can be represented on the order of micro-cents (10-6)... or even
| smaller.
|
| To give a concrete example, Ethereum has a lot of precision (1
| ether = 10^18 wei), and there are like 120M ether, so that's more
| than 64 bits just to represent the supply.
|
| Idk though, is this a real concern with traditional finance?
| Zimbabwe had their huge bills, but I assume the small ones were
| unused. Just like you round US cents, you could probably round
| their currency at some cutoff. If you were processing Ether
| outside the blockchain like just some other currency, you'd
| probably round somewhere too. If you look at Stripe's API for
| example, they do everything with fixed-size (JSON's 53-bit)
| integers defined as cents or whatever.
| blibble wrote:
| > Idk though, is this a real concern with traditional finance
|
| CME have contracts with 1/128ths of a dollar
|
| they also have a tenancy to add another power of 1/2th every 10
| years or so
|
| this causes problem for fixed point, but amusingly this works
| perfectly well with floating point
| hot_gril wrote:
| One annoyance with floating point binary is when it happens
| to not line up so well with floating point decimal, for
| example >>> 0.1 + 0.2
| 0.30000000000000004
|
| which is still gonna round to 0.3, but ugh. Also, during
| aggregations, it's not nice how you get different answers
| depending on the order of operations when they shouldn't
| matter.
| blibble wrote:
| on CME they're not decimal though, they're binary fractions
|
| so floating point works fine as floating point is binary
| fractions
| JeremyNT wrote:
| > Idk though, is this a real concern with traditional finance?
| Zimbabwe had their huge bills, but I assume the small ones were
| unused. Just like you round US cents, you could probably round
| their currency at some cutoff. If you were processing Ether
| outside the blockchain, you'd probably round somewhere too.
|
| Yeah... I started reading this article and was waiting for the
| crypto angle, because in normal finance I don't see how it
| could plausibly matter (disclaimer: not my domain).
|
| The only reason I could imagine needing to track this level of
| precision on fractional units of currency was the sort of
| financial trickery that is enabled by cryptocurrencies.
| hot_gril wrote:
| Even in cryptocurrency, I feel like the level of precision is
| mainly aspirational + cuz they can. Who cares about 1 wei in
| the context of a transaction that costs around 100 trillion
| wei on its own? The smallest unit of ether I've ever seen in
| any kind of UI is 1 gwei (1 billion wei).
| hot_gril wrote:
| Forgot to also add, cause various parts of a cryptocurrency
| ecosystem are much harder to change than traditional
| finance. So I can see why they throw in a ton of 0s and use
| 256-bit ints just in case.
| jorangreef wrote:
| Yes, we actually held out on the digital currency angle.
|
| What tipped the scales, was realizing that this applied also
| in normal finance, especially exchanges (not crypto) that
| operate with high precision:
| https://news.ycombinator.com/item?id=37573939
| jgalt212 wrote:
| An argument over fractional pennies costs full dollars of
| peoples' time.
|
| - Anonymous
| schmichael wrote:
| I find the "no negatives" very confusing even in a double entry
| ledger for reasons the last sentence of that paragraph hints at:
|
| > When you need to take the net balance, the two balances can be
| subtracted accordingly and the net displayed as a single positive
| or negative number.
|
| This means you have to reconcile credits and debits using a
| different type than each of the columns is in. Not a huge deal by
| itself, but now that secondary type has to be a weird 129 bit
| integer (or larger) to ensure it can represent every intermediate
| sum of credits and debits.
|
| If they just would have sacrificed 1 bit they could have used a
| single signed 128 bit data type for all storage and computation.
|
| I suspect they have to enforce the "all debits and credits are
| positive" invariant in a number of places anyway (or risk
| coercing a negative signed 128 input into an unsigned 128 but
| ledger entry), so why not sacrifice a bit that will probably
| never be used otherwise anyway and have a uniform structure for
| numeric types?
| feoren wrote:
| Using a single signed 128-bit integer does not solve this. What
| happens when you have to add two of these together? Do you need
| a 129-bit signed integer? What about if you need to add 64 of
| these together; do you need a 134-bit signed integer? The point
| is that 128 bits is well large enough to hold the sum of
| quadrillions of transactions in Zimbabwean dollars. Nobody is
| switching to a 129-bit number to hold the results of sums; they
| are explicitly not handling the case where any account is
| anywhere close to 10^38 of the base unit.
| jorangreef wrote:
| Yes, we could have explained this more! (Joran from TigerBeetle
| here)
|
| The motivation is to preserve information, and I think this
| becomes less confusing once you understand that accounting is
| in fact a type system.
|
| I hope this comment makes this more clear:
| https://news.ycombinator.com/item?id=37571942
| Animats wrote:
| Next, people will want 128-bit/128 bit rational arithmetic for
| money. Then fractions will work right.
| jorangreef wrote:
| cf. https://news.ycombinator.com/item?id=37573939
|
| (TLDR: It's the 10^10 precision in trading systems that gets
| you.)
| perihelions wrote:
| I see your 10^14 Zimbabwe Dollar Note and raise you this 10^20
| Hungarian pengo,
|
| https://en.wikipedia.org/wiki/Hungarian_pengo (caption: _" 100
| million trillion (100 quintillion) pengo (1946)"_)
|
| At its nadir (US$ 1.0 = 4.6*10^29 P), a reasonable-sized
| transaction denominated in, for example, micro-pengos, would have
| overflowed a uint128_t.
|
| Conclusion: just use floating point, it's inflation-proof.
| zephyrus76 wrote:
| It's interesting that even the current financial system fits so
| snugly into 2^64! Global GDP = $100T = $10^14. If we imagine
| global assets being worth 10x GDP, that's $10^15. 2^64 = 1.8 *
| 10^19. If people care about measuring values to precision at
| $0.0001, that's about the limit.
| belter wrote:
| https://www.joda.org/joda-money/
| onetimeuse92304 wrote:
| Specialising in financial software, over the past 2 decades I
| have been fighting over this with countless people, teams and
| companies.
|
| For accounting you should only ever use arbitrary precision math
| library with ability to specify rounding rules. If your
| programming environment/language does not have one, it is
| unsuitable to be used for accounting, billing, invoicing,
| payments, etc.
|
| Having the underlying library is, of course, not enough. You also
| need to be able to properly store (data structures, databases),
| transfer (wire formats, data structures), process (order of
| operations, rounding rules), present (UI toolkit) and so on.
|
| I have never in my life joined a software project for any
| organisation that was able to do basic arithmetic on money
| correctly (and I worked for companies ranging from small startups
| just needing invoices and very simple billing to risk management
| departments for largest financial institutions on Earth
| processing trillions of dollars on a daily basis).
| singleuse715185 wrote:
| nobody cares about precision in financial calculations except
| for nerds. particularly areas like reporting tend to have
| significant errors, and not just sigma.
|
| this is now a fintech anecdotes thread, but my first ever
| fintech job was part of a two man special priviledges team
| directly under a director of X at one of the sifis. we were
| supposed to cut across multiple departments and through red
| tape with the main goal if eliminating significant overhead in
| certain processes (we brought some multi-day multi-step
| calculations down to 8 minutes in one instance, 2 minutes in
| another, kept us on a vendor list for a very very very long
| time). i didn't know how things are done, so i used bigdecimal
| throughout, with a lot of precision and explicit rounding
| rules. i did back of napkin numerical analysis for at least
| inner loop code. we duplicated work done by other departments
| (!!!), things like instrument pricing, because we couldn't wait
| for their batch jobs to complete. at the end we were getting
| from slightly to wildly different results. it took a lot of
| conversations with business to realize that 1) our calculations
| were correct 2) for them to realize what the sources of errors
| were and where they were coming from 3) for everyone to just
| kind of go eeeehh not a big deal.
|
| i wrote a translator for a subset of j/k to java bytecode using
| java asm, i was pretty proud of that system, because it allowed
| to express pricing rules in a what i thought was much more
| readable way, dynamic reload without restart, but man i am very
| very sorry for the developers who inherited that system.
| pjc50 wrote:
| I did join somewhere that could do it correctly, because they
| had some very long-running POS software. It could even do
| things like "split bill three ways" correctly allocating both
| the spare penny from the division _and_ the tax calculation,
| such that you could add the bills back together again and get
| the same numbers as the split bill.
|
| Using a "money" class that stores things as integer pennies
| gets you a long way there. "Division" and its close friend
| "multiply by noninteger number" are the only real problems, so
| you need to be careful not to provide a generic method and
| instead methods like divideWithLocaleTaxRounding(). You also
| need to check whether you're supposed to apply tax per-item or
| you can do it to the whole bill.
|
| I think we had a "apply tax to whole bill but then re-
| distribute it to line items" method, which guaranteed that the
| total would be correct.
|
| There are reasonable arguments for "integer decimal fraction of
| penny" as the correct unit. Digikey price some parts in 0.1 of
| a penny or cent, for example.
|
| Attempting to convert things between binary "fractions"
| (floating point) and decimal fractions will result in misery.
|
| I think we also had a "rational number" class for storing
| things like "1/3".
| amalcon wrote:
| Integer cents is fantastic for POS software and similar
| things that deal with at most a few thousand dollars at a
| time. The place where it starts to fail is when the absolute
| numbers get really large, not really small. Think "United
| States Federal Reserve" or "UBS". Then remember that some of
| these institutions need to deal with accounts denominated in
| Zimbabwean dollars.
| HWR_14 wrote:
| The current US national debt represented in integer cents
| requires 52 bits. It can trivially increase 4,000x before
| we need to worry about 64-bit balances.
| ignite wrote:
| Peak inflation in Argentina was 20262.80%.
|
| So, not as much margin as one might think.
| [deleted]
| tim333 wrote:
| Python can deal with 1000+ digit integers and you can store
| them as strings in the database. Not sure about other
| languages.
| onetimeuse92304 wrote:
| Funny thing, I actually wrote one POS application
| (magstripe + EMV chip & pin + contactless).
|
| EMV uses integers encoded as BCD for money. If I remember
| well, in most cases it is 6 bytes or 12 digits. That is
| more than 2^32 (most of POS machines were 32 bit ARM until
| relatively recently).
|
| The terminal I worked on had 32 bit ARM. Rather than
| convert 12 digit numbers to 32 bit integers I decided to
| write my own arithmetic library that did operations
| directly on BCD strings of arbitrary length (but, in
| practice, EMV only allows 6 bytes for the amount anyway).
| masklinn wrote:
| Really small can be an issue when it gets _really_ small
| e.g. tarsnap's accounting is pretty infamously done in
| attodollars (1e-12). U64 only has room for 19 decimal
| digits so you're limited to 7 figures up.
| cperciva wrote:
| Tarsnap's pricing is in picodollars (1e-12) but the
| accounting is attodollars (1e-18). Tarsnap uses 128-bit
| balances -- 64 bits of attodollars and 64 bits of whole
| dollars.
|
| If I ever have someone paying me more than 2^64 dollars,
| I'll rewrite Tarsnap's accounting system.
| [deleted]
| throwaway894345 wrote:
| What are the specific challenges to writing financial software?
| What are common mistakes you see? What are common data
| structures for representing money (both the common incorrect
| implementations but also the correct implementations)?
|
| Also, provided you have a data structure that can represent
| money, you should presumably be able to serialize that data
| structure and store or send it just like any other data, right?
| Why do you need special database or wire format support? The
| trivial example is to marshal it to JSON put it on disk or
| write it to the network using the protocol suite of your
| choice, right?
| onetimeuse92304 wrote:
| I never said you need special database or wire format. Maybe
| if you are using JSON, transfer monetary values as strings
| rather than decimal or float data types. Some databases can
| actually handle money, some don't. Those that do not, usually
| require you to store money as strings to not lose
| information. When you get warned by your DBA that the
| database can't do arithmetic on strings, tell them that
| "thank you, it could not do correct arithmetic anyway".
| HerculePoirot wrote:
| Just use integers, and fields ending with "_cents". There
| is no ambiguity, rounding problems are not even an issue,
| serialization and deserialization will pose no problem when
| dealing with external actors, and you can still sum money
| easily in your db requests.
|
| Problems will arise when you'll do multiplicative
| operations on money, for instance when working out taxes.
| There are precise rounding rules to apply, and the solution
| is to tackle these issue one abstraction layer above, on
| the operations rather than the values, because some time
| you'll want to carry out rounding between each tax
| operation, sometimes at the end, on one line or on a whole
| batch of transactions.
|
| Other problems you'll bump into is the asynchronous nature
| of money flows. You won't realize it with credit cards
| (well you'll figure it out soon enough when you'll stumble
| upon "race conditions"), but this becomes explicit when
| dealing with mandates, direct bank transfers or checks. You
| need to move the money out of sight of the user in a ledger
| specific to that person that holds transactions being
| processed (can takes days or weeks in some case) and move
| it back to the original ledger if the transaction fail.
| Otherwise you'll bump into issues of double spending. This
| is something that is out of your control sometimes (had the
| unfortunate experience to issue withdrawals multiple times
| on a big bank's payment processor API and theses dunces
| sent the money multiples times). Use idempotency keys
| profusely as well as (distributed) locks. The hardest part
| is not getting your part right, it's handling external
| actors bad implementations. Also fuck HTTP w/ hooks. Some
| actors do not even make sure you received the webhook. The
| non binary aspect of HTTP is a bullshit argument and I'd
| gladly trade it for a binary protocol that has strong
| quality of service mike MQTT, since anyway I'll have to
| implement some kind of smart broker when issuing orders to
| a shitty HTTP api anyway.
| throwaway894345 wrote:
| You said something to the effect of "it's not enough to
| have financial libraries, you also need storage (e.g., db)
| and transfer (e.g., wire formats)" which suggests that you
| can't just use a standard library to dump JSON to a file or
| through an HTTP connection.
|
| But yes, I can see how databases not having a money type
| with corresponding routines is going to make life harder.
| SoftTalker wrote:
| If your database has a MONEY or CURRENCY data type, use that.
|
| Just as you should use proper DATE or DATETIME data types for
| time and not roll your own with strings, integers, seconds-
| from-epoch, or any other schemes at least if you want to keep
| your sanity.
| lxgr wrote:
| > If your database has a MONEY or CURRENCY data type, use
| that.
|
| But hopefully only after understanding how it treats these,
| and whether that's compatible with your requirements.
|
| > Just as you should use proper DATE or DATETIME data types
| for time and not roll your own
|
| I'm always happy to use the database's date/time format -
| if it's actually implemented in a sane way and is
| compatible with my data.
|
| For example, I work with data provided by external partners
| that specifies dates:
|
| Sometimes they're only specifying the year as a _single-
| digit integer_ (and you have to guess which one they mean,
| based on the current date and the hope that the files they
| send you are not older than 5-10 years). Sometimes there is
| no year at all. Sometimes the timestamps have an implied
| timezone, sometimes they 're UTC, and sometimes they're
| _supposed_ to be UTC, but really are in some unspecified
| local timezone.
|
| In these cases, it can indeed be better to store these as
| strings and deferring interpretation until you actually
| process them.
| out_of_protocol wrote:
| String (json), decimal/numeric (db) is enough to passively
| store amounts. Calculations and rounding going to be funny
| though. E.g. split $10 bill in 3 exactly the same parts,
| store, sum up to $10 again
| TN1ck wrote:
| Are there actually some systematic approaches to handle
| these cases? Or are there some libraries making this
| easier? We have so many places where we keep track of the
| offset and spread it over the items afterwards to mitigate
| this. It's annoying as it's most often a two step process
| and e.g. becomes even more complex when you have constrains
| on the numbers like applying discounts.
| koliber wrote:
| In this particular case, it's easier to think of the
| problem as "allocating $10 among 3 parties" rather than
| "dividing $10 among 3 parties." The latter insinuates
| equal distribution. Often, having the 3 parts sum back up
| to $10 is more important than giving an extra penny to
| one person and not dividing equally.
|
| What I've used before is "Express the value in pennies.
| Divide by X (number of parties). Take the whole number
| part and give it to each person evenly. Take the modulus
| and distribute it one by one to each remaining party,
| until there is nothing left."
|
| Example: allocate $10.01 among 3 parties:
|
| 1. You have 1001 pennies
|
| 2. Divide by 3 - give each person 333 pennies
|
| 3. Take the modulo 1001 % 3 - you have 2 pennies
| remaining. Time to distribute them round-robin!
|
| 4. Give one penny to person A. You have 1 penny
| remaining.
|
| 5. Give one penny to person B. You have no pennies
| remaining.
|
| If you do this many times, randomly establish the order
| of the parties each time you round-robin them. In that
| case, no one will be systematically under-allocated, just
| because their name starts with the letter Z.
|
| This is not a universal truth, and each situation is
| different. It may not apply to other kinds of money
| dividing situations.
| frankreyes wrote:
| Many decades ago I worked in a Java team who they were using
| some money as a double and some as a BigDecimal. When I asked
| why, ... they said that at the start they didn't think they'd
| have any issue with doubles. Years later and still had lots of
| tech debt because manually rounding doubles to BigDecimal.
| GTP wrote:
| What would be the problem with TigerBeetle's approach to use a
| smaller and configurable unit of measure so that you only have
| to deal with integers?
| lxgr wrote:
| The article and the comment you're responding to aren't even
| talking about the same thing, so it's futile to discuss the
| pros and cons.
|
| The article is talking about serialized representations, i.e.
| how you store amounts in a database. The comment is talking
| about how to arrive at amounts as part of arithmetic
| calculations, e.g. determining interest, percentage fees etc.
| r00fus wrote:
| > For accounting you should only ever use arbitrary precision
| math library with ability to specify rounding rules
|
| Do these rounding rules need to vary by jurisdiction?
| ska wrote:
| Absolutely. IIRC most tax codes have specific rounding rules.
| Also e.g. some countries have done away with pennies or penny
| equivalents and have rules about how you are supposed to
| handle that, etc.
| nly wrote:
| In my experience most financial firms just use binary
| floats/doubles
|
| Fixed point decimal if you're lucky (or unlucky, since fixed
| point sucks)
|
| Arbitrary precision decimal floating point essentially never
| used
| _glass wrote:
| As much as SAP has problems, this is a solved problem there. In
| my experiences sometimes this is implemented incorrectly, but
| discovered very soon, as it's about money. I encountered this
| when people made some simple calculations on the frontend-side
| then submitting to the ERP system, where it was discovered
| because of the emerging inconsistencies.
| ars wrote:
| Having an arbitrary precision library configured to use cents
| is not enough.
|
| Over a full year it needs to keep track of all the rounding it
| does when it pays you interest and when that rounding reaches a
| penny it's supposed to pay you that penny.
| tgv wrote:
| For very simple billing, arbitary precision sounds like
| overkill, as do rounding, and order of operations.
| Nzen wrote:
| I enjoyed Mark Dominus's blog post [0] about the billing
| system he cowrote, moonpig. It restates much of the other
| responses, namely that ignoring infinitesimal errors/rounding
| would have instilled a culture of - at minimum - doubt.
| Perhaps another way to see this is to look at a visualization
| [1] of the discontinuous coverage that floating point gives
| to the numbers we want to represent.
|
| [0] https://blog.plover.com//prog/Moonpig.html#fp-sucks
|
| [1] https://observablehq.com/@rreusser/half-precision-
| floating-p...
| onetimeuse92304 wrote:
| Oh, sure, because when you are a small company you don't care
| that people get correct invoices.
|
| I can certainly sympathise with this stance. There is about a
| billion things you can do better but you have limited time to
| do anything so you have to prioritise. And if one invoice in
| ten thousand is incorrect by one cent, and only one client in
| ten thousand who received the wrong invoice will actually
| find it out, then it is hard to argue you should be spending
| time on fixing this one problem.
|
| Just don't say you can do accounting correctly on floats and
| we will remain friends.
| tylergetsay wrote:
| For simple accounting I've always used integers and done
| all operations in cents, only converting on the frontend.
| what's my downside here? I guess it wouldn't support unit
| prices less than a penny
| TheCoelacanth wrote:
| Also many types of operations could give you the wrong
| result from incorrect rounding. E.g. let's say you're
| calculating 10% of $1.01 ten times and adding the result
| together. The correct result is $1.01, but with your
| method you will get $1.00.
| projektfu wrote:
| The correct answer will depend on the specifics of your
| environment. In some places, tax is calculated per line
| item. If you go to a dollar store and buy 10 items with
| 7.3% sales tax, it adds up without those 0.3C/ bits. In
| other places, the tax is supposed to be calculated on the
| total for the tax category in the sale. If you wanted to
| keep it by line item you'd need the extra digits of
| precision.
| TheCoelacanth wrote:
| Well, yes, which is why you need to be in control of your
| rounding and not just let the width of data type you
| chose for the implementation dictate that.
| mrloba wrote:
| If you have different currencies you need to keep track
| of the number of decimals used, e.g. YEN has 0 decimals,
| bitcoin has 6, etc. It could even change over time like
| Icelandic ISK did in 2007. If you have different services
| with different knowledge about this you're in big
| trouble. Also prices can have an arbitrary number of
| decimals up until you round it to an actual monetary
| amount. And if you have enough decimals, the integer
| solution might not have enough bits anymore, so make sure
| you use bigints (also when JSON parsing in javascript).
|
| Example in js: Number(9999999.999999999).toString() // =>
| 9999999.999999998
|
| And make sure you're not rounding using Math.round
|
| Math.round(-1.5) // => -1
|
| or toFixed
|
| (2090.5 * 8.61).toFixed(2) // => 17999.20 should have
| been 17999.21 8.165.toFixed(2) // => 8.16 should be 8.17
|
| The better solution is to use arbitrary precision
| decimals, and transport them as strings. Store them as
| arbitrary precision decimals in the database when
| possible.
| kawhah wrote:
| Let me guess, the last 10 times you had to move jobs it was
| because of a difference in opinion with your boss about the
| importance of correcting one-cent-errors in one invoice out
| of every ten thousand?
| onetimeuse92304 wrote:
| Haha... no. But I may be focusing way more towards the
| reliability than 99.99% or so developers.
|
| The way I solve this problem isn't by constantly hopping
| projects. I try to find projects that actually require
| extreme reliability so that I can be doing what I want in
| an environment where there is a business case for it.
| themerone wrote:
| You can make the same arguments against fixed precision
| decimal types. My systems represent currencies to 4 decimal
| places. At that level of precision, rounding/order of
| operations errors could accumulate much faster than with a
| 64 bit float.
|
| Decimals are still the way to go, you just have to pick a
| level of precision acceptable for your application.
|
| My management definitely does not want me spending my time
| chasing errors over fractions of a pennies. The only time
| those errors are discovered is when I compare the output of
| new code against old code.
| lxgr wrote:
| The article is about data types for storage, not for
| intermediary values used as part of calculations, though. Are
| you proposing that everybody is storing monetary values
| "wrong", too?
|
| And as a meta-point:
|
| > I have been fighting over this with countless people, teams
| and companies. [...] I have never in my life joined a software
| project for any organisation that was able to do basic
| arithmetic on money correctly [...]
|
| Are you absolutely sure that you are the _only person_ that
| understands how to do accounting arithmetics on computers
| correctly?
|
| My guess would be that the status quo is a combination of a lot
| of legacy code and procedures, but more importantly of
| differing priorities.
|
| Maybe you value arithmetic correctness over simplicity of
| procedures (sometimes these need to be published in regulatory
| texts or even laws) or compatibility with other entities and
| their procedures much more than the industry average?
| manicennui wrote:
| I agree with the parent. Almost everyone thinks floats are
| fine. I work in lending, and many of my coworkers, who claim
| to have CS degrees, do not understand floats at all.
| lxgr wrote:
| GP isn't just saying "don't use floats", though. (And even
| that is only a heuristic: It's possible to get correct
| results using floats, but you need to be very diligent
| about when and how you round, so in practice it's easiest
| to just avoid it.)
|
| They're saying that only arbitrary precision arithmetics
| are acceptable, and additionally claiming that everybody
| else in the world gets money arithmetics wrong.
|
| I doubt both of these statements, and especially the
| assertion that there's exactly one "correct" way of doing
| arithmetics with money.
| manicennui wrote:
| Arbitrary precision decimals are the best solution in
| most cases. I have worked at multiple companies where
| people represent currency with floats and then wonder why
| they get strange results in some cases.
| zie wrote:
| Floats are not how you do money math, if you run into anyone
| trying to do money math and they say they use floats, there
| is a 99.999999% chance they are wrong.
|
| > Maybe you value arithmetic correctness over simplicity of
| procedures
|
| Lots of places(not typically the USA) has this codified in
| law. For example, do a web search for: EU money rounding
| rules. You will find several different rounding and precision
| rules, depending on the context of what you are doing with
| the money, all from places like the Central Bank and the EU
| Commission.
|
| It's mostly US developers that are clueless here, because US
| laws are fuzzy at best, and the general rule is, you do
| whatever _your_ bank /regulatory authority does, and if they
| don't happen to know (and I've met several that don't), then
| you have to figure it out yourself.
|
| In the USA, we use decimal.ROUND_HALF_UP, because we have
| seen in practice this is what our USA based banks & govt tend
| to do in the wild. It should be noted IEEE 754 rounding
| recommends using decimal.ROUND_HALF_EVEN.
| https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules
|
| In other places, we do whatever their laws require, or treat
| them like the USA and do whatever our local bank/govt
| authority tends to do in practice.
| vidarh wrote:
| A shocking number of people (edit: who implement billing
| related software) are unaware of how many decimal points of
| accuracy their local tax code requires to calculate vat or
| sales tax correctly. And those things _are_ often specified
| in terms of arithmetic correctness.
|
| I had our CFO stand behind me while I talked him through
| every step of our VAT calculations once, because he was
| legally responsible if I made us round it wrong, to the wrong
| number of digits. And had we e.g. done something grossly
| incompetent like used floats for those calculations it most
| certainly would have been wrong, but so would it if I used
| fewer than five digits past the decimal point or failed to
| round in the right direction after that.
|
| It's usually not hard, but it requires being aware that you
| need to look up the right rules. And know better than using
| floats.
| ignite wrote:
| > A shocking number of people ... are unaware of how many
| decimal points of accuracy their local tax code requires to
| calculate
|
| A shocking number of people who create tax codes have no
| idea how many decimal places they are using.
|
| It's probably better now, but I recall having to reverse
| engineer the tax tables to figure out how many decimal
| points of accuracy were used, and what rounding rules were
| used, so we could match their numbers.
|
| These numbers would change from year to year, with no
| change in the underlying tax codes.
| vidarh wrote:
| I always hated tables. At least when I last had to
| implement UK VAT rules the rules were _very_ precisely
| defined. But I 've had to deal with stupid tables
| implementing rules they couldn't be bothered to spell out
| before. Yikes.
| itsoktocry wrote:
| > _A shocking number of people are unaware of how many
| decimal points of accuracy their local tax code requires to
| calculate vat or sales tax correctly._
|
| What is your jurisdiction? In Canada, I can't for the life
| of me _imagine_ the CRA would remotely care about decimal-
| point accuracy. In fact, most of their online forms
| explicitly _remove_ the decimals.
| hedora wrote:
| I think the point is that the integer arithmetic
| implementation your CPU provides is wrong in at least one
| jurisdiction, so (for example) the machine code in the
| article is wrong.
| vidarh wrote:
| UK. The rules may have changed now, it's a long time
| since I implemented the rounding rules here, but the last
| time I did it required 5 decimals accuracy. The rules
| also used to specify how you needed to account for line
| items vs. sub-totals in your invoices to ensure you
| didn't find any "workarounds" to shave off some pennies
| of tax (In fact, the last time was while the tax
| authority was still called the Inland Revenue, which it
| hasn't for years.)
|
| For _aggregate totals_ of your VAT liability across your
| total set of invoices, you 'd be fine with rounding up to
| the nearest pound, to the Inland Revenue's benefit. For
| _individual invoices_ however, you were required to stick
| to very specific rounding rules.
| ta1243 wrote:
| > For aggregate totals of your VAT liability across your
| total set of invoices, you'd be fine with rounding up to
| the nearest pound, to the Inland Revenue's benefit
|
| On personal tax forms you have to round in the taxpayer
| favour. If your income is 12345.67 you round it to 12345.
| If your expense (say giftaid) is 12345.67 you round it to
| 12346.
|
| Surprised it's the other way with VAT, but then I do very
| little with tax other than click a few buttons and
| confirm "yes, you have to tax me as I have children".
| vidarh wrote:
| I'm not sure it's the other way with VAT, as I said it's
| been many years and the rules may well have changed
| multiple times.
|
| The key, though, is that with taxes, if at all unsure
| you've got the rules right, the safest option is to round
| in the tax offices favour.
|
| It's in general a lot less painful to explain an
| overpayment than underpayment if something is broken.
|
| Of course, better yet, get it right.
| lxgr wrote:
| That's for final amounts though, right?
|
| I bet they care about you not throwing away decimals in
| intermediate calculations for VAT or sales tax.
| [deleted]
| j16sdiz wrote:
| in my experience, these are often written off as error.
|
| if the error is less than their hourly salary rate, it
| don't even worth mentioning.
|
| if it worth a day or two of salary, its nice to fix but
| never a priority
| vidarh wrote:
| For it to be written off as error you need to know the
| discrepancy, which means you need to know what it's
| supposed to be. When e.g. calculating the VAT or sales
| tax you owe the government, if the rounding deviates from
| legal requirements then unless it's in _their_ favour you
| can be in for a bad time.
| pixl97 wrote:
| I think for most large businesses there are pretty
| considerable error bars here. If you say you owe
| 1,000,000 a year in VAT and the government says you owe
| 1,010,000 it's cheaper to pay the difference then dig
| into why it's off.
| vidarh wrote:
| If you _report_ 1,000,000 and _certify_ that it 's the
| right number, and the government audits you and find you
| should have paid 1,010,000, then depending on
| jurisdiction you might be entirely ok, or you might find
| you're not going to be paying just the difference, and
| interest, but also a fine, and bearing the cost of
| additional audits going forward, and that your finance
| director will not appreciate having to address questions
| aimed at figuring out whether anything criminal is
| involved. Repeat the mistake a few times, and the level
| of scrutiny will escalate.
|
| There's a reason that in 28 years of working in software,
| the only thing the financial teams I've worked with have
| obsessed over have been whether or not we get the VAT
| calculations right, and the "sticker price" of the
| discrepancy has _never_ been what they worry about. For
| calculations that does not involve getting tax amounts
| wrong, they often couldn 't care less about much bigger
| discrepancies, but get tax wrong in the wrong
| jurisdiction and it's a lot of pain.
| leosarev wrote:
| It's strange. In Russia, small error in VAT will get you
| a letter from tax service "pay us a small error
| voluntarily, or we will schedule an inspection". Letter
| will be automatically generated by ASK-NDS system
| (translated as Auto Check Vat).
| ta1243 wrote:
| How do they know there's an error?
| helpfulmountain wrote:
| Why would it be wrong to use floats?
|
| That would have been my default assumption
| GeneralMayhem wrote:
| Floats lose precision unexpectedly with certain fractions
| that are perfectly representable in decimal, and also
| with certain integers once you get high enough.
|
| The standard in ad-tech (not sure about banking) is to
| use int64s representing either microdollars or
| microcents, so a max capacity of 9.3*10^13 or 10^11
| dollars
| macksd wrote:
| When you're doing floating point arithmetic on a
| computer, it will approximate and round certain values in
| ways that don't match the way humans do it when they're,
| e.g. doing accounting.
|
| So you need to run a massive physics simulation really
| fast? Yes, floats are great.
|
| You need to calculate taxes on a massive corporation's
| fiscal year? Bad idea.
|
| Some libraries advertise "arbitrary precision", many
| computer systems have a "decimal" type intended for
| currency, etc. and then they won't make all the same
| mistakes, but as the OP said you still need to control
| rounding rules and make sure they match the law.
| Dylan16807 wrote:
| > You need to calculate taxes on a massive corporation's
| fiscal year? Bad idea.
|
| That depends on whether the hundred-billion-dollar
| corporation cares about being off by a dollar.
|
| And by "off" I mean "different from how humans round",
| not necessarily further away from an infinite-precision
| calculation. In fact at "massive corporation" level I
| would guess that binary floating point is _more_ accurate
| than a typical fractional penny system.
| hiatus wrote:
| > That depends on whether the hundred-billion-dollar
| corporation cares about being off by a dollar.
|
| How many hundred billion dollar corporations are private?
| Public companies would care a great deal about accounting
| accuracy.
| Dylan16807 wrote:
| Is it worse for a hundred billion corp to be off by a
| dollar than for a hundred million corp to be off by a
| third of a penny?
| chasd00 wrote:
| it's not so much how much it is off but that it's off at
| all. If the numbers don't add up then they don't add up.
| If there's any kind of difference then it has to be found
| and accounted for and it becomes a needle in a haystack
| search to account for the difference. Think about trying
| to find $0.05 spread across hundreds of thousands of
| transactions due to rounding issues.
| ilyt wrote:
| > 0.3-0.2-0.1
|
| -2.7755575615628914e-17
|
| And now you overdrafted
| Dylan16807 wrote:
| Decimal systems have to round too, so that's a pretty
| weak dismissal.
| lxgr wrote:
| Floating point calculations without some final rounding
| step before presentation/export/storage are almost always
| wrong, since you're implying much more precision than is
| justified by your source data.
| munificent wrote:
| Ths problem isn't rounding the final result. The problem
| is that the source data itself can't be accurately
| represented.
|
| There is no floating point value equal to 0.3.
| lxgr wrote:
| That's not a problem by itself.
|
| You can represent 0.3 as 0.300000...0004, which rounds to
| 0.3 again in the end.
|
| But you need to reason about the number and nature of
| intermediate operations, which is tricky, since errors
| usually accumulate and don't always cancel out.
| jjgreen wrote:
| Do it a million trillion times and we're talking cents
| overdrafted (almost)
| vidarh wrote:
| If you just add up the errors, sure. What is riskier is
| that you risk tipping values the wrong direction right
| before applying a rounding step, or end up with an error
| right before multiplying a now wrong per-unit value with
| some large-ish factor.
|
| Often these things are not a big problem on their own,
| but then later gets compounded because someone does
| something stupid like passing these imprecise values
| around to be distorted further all over the place.
|
| And sometimes the reason it doesn't become a legal
| problem turns out to be because your finance department
| quietly works their way around it by expending expensive
| manpower accounting for discrepancies that shouldn't be
| there in the first place, and so increases the cost to
| the business by many magnitudes over the loss the
| developers might have assumed to be the worst case (if
| they're aware of the discrepancy at all).
|
| This is one of those things you can get away with many
| times, many places, with no ill effects. But _when_ it
| finally bites you it can get expensive and /or really bad
| to deal with, and it's fixed by simply never doing money
| calculations on datatypes with imprecise arithmetic, and
| having a five minute conversation with your finance team
| about what your local rules for rounding tax amounts are.
| perihelions wrote:
| - _" or end up with an error right before multiplying a
| now wrong per-unit value with some large-ish factor."_
|
| Where in financial accounting do people multiply an
| amount of money by a multiplicand larger than order-of-
| unity?
| vidarh wrote:
| In _accounting_ , no, while preparing _input_ to the
| accounting in the form of generating invoices, I 've lost
| count (sorry) of the number of times I've seen people
| doing tax calculations etc. on unit prices and then
| multiplying by number of units ordered, and then further
| compounding potential issues by adding up these numbers
| from multiple invoice lines. None of which is usually the
| right thing to do, all of which you _often_ "get away
| with" without causing sufficient discrepancies, and so
| which people often fail to catch in testing. Until you
| suddenly don't.
| perihelions wrote:
| - _" multiplying by number of units ordered,"_
|
| Yeah, that's one example. I wasn't imaginative enough;
| thanks!
| Shish2k wrote:
| If a rounding error put me a million-trillionth of a cent
| into my overdraft, I'm pretty sure my bank would still
| activate that $20/mo overdraft fee :P
| PH95VuimJjqBqy wrote:
| floats are an imperfect representation of real numbers
| and as such, there are an infinite count of real numbers
| that cannot be accurately represented with floats (and
| doubles).
|
| It gets even worse when you start doing calculations on
| floats/doubles.
|
| These inaccuracies are ok for a lot of things. graphics
| often uses floats and the errors are small enough they
| don't matter.
|
| But currency absolutely needs to be accurate, and for
| that reason, floats/doubles are in appropriate.
| dspillett wrote:
| Surprisingly common values like 0.1 don't have a precise
| representation in binary for most formats, including
| standard floating point number formats. See
| https://0.30000000000000004.com/ for more detail than you
| can shake a stick at.
|
| Also if the local tax code states using 5 decimal places
| for intermediate values when you will introduce "errors"
| using formats that give greater precision as well as
| those that give less precision. Having worked on mortgage
| and pension calculations I can state that the (very)
| small errors seen at individual steps because of this can
| balloon significantly through repeated calculations.
|
| Furthermore, the name floating point gives away the other
| issue. Floating point numbers are accurate to a given
| number of _significant figures_ not _decimal places_. For
| large numbers any decimal places you have in the result
| are at best an estimate, and as above any rounding errors
| at each stage can compound into a much larger error by
| the end of a calculation.
| TacticalCoder wrote:
| The biggest issue is you now need programmers who know
| about epsilon computation and error propagation when
| working with incorrect numbers. Then you need to know
| when to fudge the visual representation of your incorrect
| number (and you probably also need to understand when
| your programming language / libraries do fudge the output
| for you).
|
| FP numbers have their use but they re better reserved for
| scientists doing actually scientific stuff and not just
| to represent what are actually tiny numbers (in the grand
| scheme of things) and which can be represented perfectly
| by other means.
| bewaretheirs wrote:
| IEEE standard floating point uses a binary mantissa.
|
| And binary has trouble representing fractions that are
| common in prices: $ bc obase=2
| scale=20 1/5
|
| 1/5 in binary is a repeating binary fraction:
| 0.0011001100110011...
|
| Just as you can't express 1/3 or 1/7 precisely as a non-
| repeating decimal fraction, you can't express 1/5 and
| 1/10 as a non-repeating binary fraction. As a result,
| most prices involving cents in currency cannot be
| expressed precisely as binary floating point numbers.
|
| edit: fixed formatting
| lxgr wrote:
| If there's an applicable law or regulation that says "you
| must do x", and you do y (and that yields different
| results), you'll get into trouble, even if your way
| yields "better" or "more accurate" results.
|
| This is not to say that using floats and rounding
| correctly necessarily _does_ yield different results, by
| the way (although most likely it will) - but if they do
| differ, you 're going to have a bad time using floats.
| cmovq wrote:
| https://0.30000000000000004.com/
| wrs wrote:
| Laws are typically written by humans, and we use base 10,
| not base 2. We think $0.03 is an exact number, but floats
| can't represent 0.03 exactly.
| Merad wrote:
| A shocking number of people who work with software that
| handles money are just winging it. I worked on a project
| once that handled payment processing functionality for
| other products at the company (it was a B2B SaaS where
| clients could take payments through our software). We also
| handled payments related billing, since the clients would
| owe fees to us and to our payments gateway for their
| transactions.
|
| The payments gateway we worked with calculated their fees
| to a thousandth of a cent, but of course we could only bill
| whole cents. So basically every billing period there would
| be a < $0.01 balance due that carried over to the next
| bill, and every so often the carryover would add up to a
| full cent that needed to be charged. When we implemented
| our MVP we (engineering) explained this to the product and
| business teams, and it blew their minds. Our suggestion was
| to have a tooltip on the 1 cent charge with a link to a
| help article explaining how the accounting worked, but they
| were strongly against it and had us list the 1 cent as
| something like "other fees" with no explanation. They
| seemed convinced it was a thing that would happen only
| rarely, even as we were telling them otherwise. Anyway,
| that 1 cent charge just infuriated clients for some reason,
| and every month or two we'd get bug reports about it or
| requests to explain why it kept showing up. Fun times...
| Dylan16807 wrote:
| Why was it listed separately at all?
|
| If the month's charges were 406.783228 and I get a bill
| for 406.79 then that seems perfectly good.
|
| If I get a bill that says 406.78, plus a separate 0.01,
| that's weird.
| Merad wrote:
| > Why was it listed separately at all?
|
| Because the bill included a detailed breakdown of all the
| fees by type and transaction. Typically our clients were
| charged a fixed monthly fee, a fixed authorization fee
| charged every time a payment was attempted (even if it
| was declined), and a fee applied to successful payments
| that was a percentage of the payment amount. There were
| other fees for things like processing chargebacks, but
| IIRC they were the same for everyone.
|
| > If the month's charges were 406.783228 and I get a bill
| for 406.79 then that seems perfectly good.
|
| Yeah, we definitely weren't allowed to round up and keep
| the change. I can't claim to know all the details
| involved but I suspect that doing so would've at least
| violated our contract with the payments gateway. Might've
| actually been illegal.
|
| > If I get a bill that says 406.78, plus a separate 0.01,
| that's weird.
|
| That's not how it worked. For the sake of simplicity
| let's assume that your activity is always the same,
| therefore you have new charges totaling exactly
| $406.783228 every month.
|
| * Month 1: You owe $406.783228, your bill is $406.78, a
| balance of $0.003228 rolls over.
|
| * Month 2: You owe $406.786456, your bill is $406.78, a
| balance of $0.006456 rolls over.
|
| * Month 3: You owe $406.789684, your bill is $406.78, a
| balance of $0.009684 rolls over.
|
| * Month 4: You owe $406.792912, your bill is $406.79,
| there's a $0.01 "other fee" line item on the bill, and a
| balance of $0.002912 rolls over.
| Dylan16807 wrote:
| I wasn't talking about rounding up. I meant exactly the
| same thing you're saying about month 4.
|
| > Because the bill included a detailed breakdown of all
| the fees by type and transaction.
|
| Was it all rounded [down] to the nearest penny?
|
| That type of bill can already fail to add up to the total
| very easily, like x.xx4 + x.xx4 + x.xx4. So I'm still not
| sure why there was a need to have a line item to explain
| this single penny.
|
| Was there only a single charge on each bill that used
| fractional pennies? So that this was the only time that
| things wouldn't add up perfectly?
| vidarh wrote:
| I think that's a case for just dropping that cent. As
| long as it's your own money and not tax you're
| underreporting it's not a problem as long as it's
| consistent.
| elcritch wrote:
| Carrying the remainder microcents as a bill seems
| overkill and not necessarily correct. Accounting
| regulations and accepted practices have well established
| rules on rounding, like bankers rounding (1).
|
| You could probably treat the extra microcents as being on
| the next pay period. Though that's annoying as if I close
| an account I'd expect it to be paid in full, not a few
| microcents remaining.
|
| 1: https://stackoverflow.com/questions/45223778/is-
| bankers-roun...
| deciplex wrote:
| > done something grossly incompetent like used floats for
| those calculations
|
| So, in another life I worked on reporting software for a
| foreign branch of a US bank. You've heard of the bank. You
| would probably recognize the CEO's name, in fact.
|
| We had been fucking this up for years. I fixed it. We had
| some customers who yelled at us because our reports were
| "wrong" i.e. they were double checking our work and
| apparently making the same mistake. They could not be
| reasoned with. Bear in mind, we're talking about
| differences of pennies, or a few dollars on very large
| transactions. Some of our customers insisted we were
| calculating the values incorrectly and demanded we "fix"
| it.
|
| What do you think happened next? You have one guess.
| robertlagrant wrote:
| > A shocking number of people are unaware of how many
| decimal points of accuracy their local tax code requires to
| calculate vat or sales tax correctly.
|
| I would imagine almost no-one knows this (-: What's a
| shocking number?
| vidarh wrote:
| > What's a shocking number?
|
| Almost every developer I've worked with who haven't
| implemented invoicing or billing at least once and had
| their finance team yell at them for producing wrong
| numbers...
|
| (and I'll edit this to add the limitation "who implement
| billing related software" - it's still true, and closer
| to my intended point)
| 38 wrote:
| > arbitrary precision math library with ability to specify
| rounding rules
|
| I got you:
|
| https://godocs.io/math/big#example-RoundingMode
| im3w1l wrote:
| > I have never in my life joined a software project for any
| organisation that was able to do basic arithmetic on money
| correct
|
| This observation should tell you that's it actually quite
| viable to be off as long as the errors are small enough.
| toomuchtodo wrote:
| The world runs on "good enough."
| lxgr wrote:
| True, but the world also runs on standards (whether
| explicitly defined or customary), and doing things
| differently from everybody else makes it painful to work
| together.
|
| Sometimes there's also value in doing something objectively
| poorly, but in a predictable and well-understood way.
|
| Unilaterally starting to "do numbers better" sounds like a
| recipe for, let's say, interesting times in the
| finance/accounting world.
| SoftTalker wrote:
| Yeah even in university in my intro-level accounting classes
| they said in the real world nobody cares about discrepancies
| less than a dollar (and that amount scales with the size of
| the business). I don't know if that's actually true and I
| wasn't an accounting major so I don't know what they said in
| the more advanced classes.
|
| But if I imagine myself as a business owner I would be
| annoyed with my accounting firm if they spent billable hours
| chasing down a discrepancy of a few pennies.
| koliber wrote:
| Years of practice have led me to this practical wisdom:
|
| As long as things are consistent, no one cares if you are
| correct. If you lose a penny in the backend calculation,
| and the frontend shows the amount without the penny, and
| the email contains the amount without the penny, and the
| PDF download contains the amount without the penny, no one
| will care that there should be a penny there.
|
| It becomes problematic if some places are wrong and some
| are right, and they are not consistent. You won't get
| credit for being right in only some places.
|
| As long as the error is small enough to be inconsequential,
| being consistent is more important than being correct.
| manicennui wrote:
| It's viable because customers generally have no recourse and
| companies don't care as long as the problem is in their
| favor.
| devmor wrote:
| As someone who works in fintech, my observation is not that
| the caveat is "as long as the errors are small enough" but
| rather "as long as whoever governs the business logic is
| aware of the impact".
|
| The size of the errors almost always is a large factor in
| their decision, but ultimately the software we write exists
| to serve the needs of the business, and if the business
| decides that larger errors are okay for some reason, then so
| be it.
| kawhah wrote:
| Quite right. Either this OP spends every day writing letters
| to banks, shops and credit card companies complaining about
| the fractional cents that they have been cheated out of,
| probably in green ink. _OR_ they should be able to recognize
| that plenty of people have good-enough solutions for this.
| forinti wrote:
| I have a personal anecdote on this subject. A long time ago I
| worked at a bank and I had to calculate a large number of
| accounts regarding agricultural loans. These were state
| sponsored loans. When I finished my task (this was a Java job),
| I found that sometimes the results were off by $0.01. So I
| asked my boss how I should do the rounding, to which he replied
| that an error of up to $1 was acceptable. If I recall
| correctly, the amounts where in the hundreds and thousands.
| rvnx wrote:
| I had such case too, the solution is simple:
|
| round in favor of the bank / financial institution you are
| working for
| yyyk wrote:
| Heh. But usually it's the other way around unless they
| remembered to specify it the right way. Forgiving $0.01*N
| customers is cheaper than dealing with an irate customer.
| seanhunter wrote:
| That is absolutely not how it works. Rounding is exactly
| specified in the underlying contract always and you need to
| implement the correct rounding. For example, here is the
| rounding table for compounding calculations in the ISDA
| definitions (these are very standard for a wide range of
| contracts, but this particular table is for various
| overnight swap rates used in interest rate derivatives)[1].
|
| [1] https://globalmarkets.cib.bnpparibas/app/uploads/sites/
| 4/202...
| prometheus76 wrote:
| Interesting side note:ASME also has a standard for
| rounding on engineering drawings. A few years back I had
| to build a custom function in Excel to match the
| standard, because our calcs weren't matching the
| customer's calcs.
| cornstalks wrote:
| And how do they round ties? Does 0.00005% round to
| 0.0001%? Is tie breaking usually included in such
| contracts?
| RandomLensman wrote:
| For these benchmarks, yes, that is defined.
|
| Where issues could come in is when these things are
| multiplied with a bunch of other numbers (each number
| with defined rounding but not after each operation) and
| then have some defined rounding at the end. There
| different computer numerics could in give slightly
| different results, but those can easily be resolved on
| settlement (for small stuff that stays well within the
| back offices - at least that is how I remember it).
|
| Also, not totally unusual for one or both participants to
| forget about some rounding they might have agreed
| bilaterally if it was some one off etc.
| onetimeuse92304 wrote:
| No, it does not work this way. Any good accountant will see
| a different in values, even smallest one, as a sign of an
| incorrect calculation. Does not matter which way it goes,
| they will feel compelled to figure out who is wrong. At
| least a good accountant will.
| rvnx wrote:
| There is no accounting error; let's say customer has
| purchased / used a service for 1.433 USD.
|
| You issue an invoice for 1.44 USD (aka, amount due), then
| the 1.44 USD is used as a basis for accounting and is all
| consistent.
|
| Then, if you are a nice company _and_ the situation
| applies in your case, you may issue a credit in favor of
| the customer for 1.44 USD - 1.433 USD that will be used
| as a discount on a future invoice
|
| The best part is that the moment where you decide to
| issue the credit invoice or not, is the perfect moment to
| track the rounding errors and even keep a very detailed
| journal of the entries (e.g. for auditors).
| meekaaku wrote:
| One can use more than 2 decimal places for rates, but
| final invoicing has to be two decimal places (atleast in
| most countries). Banks/tax authorities dont carry
| anything beyond 2 decimal.
|
| Eg: fuel is usually priced 3 decimal, so 4 gallons x
| 25.5444 usd/gallon gives = $102.1776 to 4 dp, but will be
| billed as $102.18
| marcosdumay wrote:
| You added 10 of those items as inventory with a total
| value of 14.33, then you sold each individually as a
| total value of 14.40. After that transaction, your
| inventory account has -0.07 on it, but there aren't any
| items at all there.
| hef19898 wrote:
| From experience, those differences surface during stock
| taking. Amd most companies are _really bad_ at that. And
| if they surfacey they are corrected by inventors
| adjustments (in unit of measure, not value, which is a
| differwnt can of worms). As long as those adjustments
| aren 't to extreme, nobody really cares.
|
| A good accountant so will sooner or later investigate
| those rounding errors, as they will show up somewhere
| ultimately. And a general policy of rounding in one
| direction is the last thing you want an auditor to find.
| eternityforest wrote:
| So accountants are like number detectives doing what's
| essentially debugging work just like a coder would?
| marcosdumay wrote:
| They design the system, detect the failures, explain and
| correct them. So, their work even is more like programing
| than your comment implies.
| bux93 wrote:
| Any rounding discrepancies simply get posted to a
| rounding-error account. For example, oracle's ledger will
| complain if there is rounding and no rounding-error
| account to post to. https://support.oracle.com/knowledge/
| Oracle%20Cloud/2411363_...
| tonfreed wrote:
| I've worked in banking.
|
| I assure you, I would have had a million bugs filed on that
| before it even hit production.
| valdiorn wrote:
| I'm assuming you did the correct thing and engaged an an
| Office Space-esque penny-stealing operation after learning
| this? :)
| onetimeuse92304 wrote:
| On my first day in a new company, not even senior dev yet, I
| met with the head accountant. I asked about her top problems,
| she said her top problem was that the application would
| produce different invoice on screen, different invoice when
| printed as PDF and a different invoice in the accounting
| software. About 1% of all invoices were affected but due to
| amount of billing they were doing (telecommunications and
| advertising) they needed to have 3 FTEs just to correct the
| invoices.
|
| And correcting the invoices meant playing with numbers so
| that at least the PDF and accounting software agreed on the
| total value and tax.
|
| She also said they had at least 2 different employees and an
| external company look at it and not able to fix it. She also
| told me not to bother because she does not believe the
| problem can be fixed (that's what she was told).
|
| I looked at the software, it had two separate copies of the
| invoice calculation (separate for on screen and for printing
| to PDF). And of course it would send the invoice to the
| accounting software which calculated the invoice in a
| different way still.
|
| I ran couple of experiments to reverse engineer how the
| accounting software did the calculations -- the exact order
| of them and the exact rounding rules. Then I built a small
| module that captured those calculations. Then I changed all
| doubles to arbitrary precision.
|
| It took two days and the problem was fixed but it took couple
| more days before accounting department actually believed it.
| formerly_proven wrote:
| > I looked at the software, it had two separate copies of
| the invoice calculation (separate for on screen and for
| printing to PDF). And of course it would send the invoice
| to the accounting software which calculated the invoice in
| a different way still.
|
| Your setup made it sound like something crazy and inane,
| like "the PDF printer used on those machines changed
| floating point rounding modes" or what have you.
| pjc50 wrote:
| There was the famous "Xerox photocopier changes digits
| sometimes" bug, but that's not what's happening here.
| onetimeuse92304 wrote:
| In olden times we would "print to PDF" as in have a
| little piece of code to format the document that would be
| sent to a printer which could be a PDF document.
|
| In this particular case we had two separate pieces of
| code, one running on the client (for on screen
| presentation) and one on the backend (to create the PDF
| on a shared location and produce a download URL).
| michaelt wrote:
| _> I looked at the software, it had two separate copies of
| the invoice calculation (separate for on screen and for
| printing to PDF)._
|
| That's actually kinda normal, in some industries.
|
| For example, an amazon marketplace seller's warehouse
| management system might not be tightly integrated with
| Amazon's basket/checkout display logic.
|
| In some situations the results of recalculating are
| _supposed to_ be different. For example, if there 's a "5%
| off when you buy 3 widgets" offer and you check out with 2
| widgets in your basket, the offer doesn't apply. But if you
| checked out 3 widgets, thus getting the offer, then the
| seller found they were low on stock and could only send you
| 2, you should get the 5% discount on those 2.
| ilyt wrote:
| > It took two days and the problem was fixed but it took
| couple more days before accounting department actually
| believed it.
|
| Those 3 people that now didn't had a job probably weren't
| all that happy xD
| em-bee wrote:
| if there ever was a reason to apply DRY at all cost, this
| is one
| giantg2 wrote:
| The hero I want to be
| onetimeuse92304 wrote:
| It is easy to be a hero when the company is shitty.
|
| My career advice is to work in a field / company / job
| where you can be somewhere in the top 10-20% of all
| employees. Just don't overdo it, if you are top 1% you
| are probably aiming too low and could be working for
| better paying, more rewarding field / company / job.
|
| For a lot of my career I was working for financial
| institutions like banks. A lot of really badly managed
| projects with definitely not top level developers. Easy
| to be a top performer. I really like helping people and
| projects and it was working well for me especially when
| it was easy for me to provide valuable help.
|
| I got hired once for a really good company with really
| top performers and suddenly I lost the status that I was
| so used to. I was keeping up with my work, sure, but I
| was no longer a shiny star. I got back to working for
| banks.
| twodave wrote:
| https://wiki.c2.com/?BankersRounding
| ignite wrote:
| People care less about the dollar value than about
| reconciling. If there is some external system they should
| match, they really want it to match exactly.
| [deleted]
| david422 wrote:
| Whenever I input my tax data on forms, it always rounded to
| the nearest dollar. It was strange that accuracy didn't seem
| to be a big priority.
| brewdad wrote:
| I imagine over millions of returns it probably evens out.
| Also, for the majority of taxpayers in the US, the tax
| table does things like:
|
| AGI is 40,001 to 40,025 then your tax is X dollars.
|
| Being accurate to the penny isn't worth the trouble.
| Vvector wrote:
| Sounds like the start of a movie script
| GoToRO wrote:
| Office Space
|
| https://youtu.be/yZjCQ3T5yXo?si=xGGrxafG2zzA0IIR
| Cshelton wrote:
| Exactly. I think many people start overthinking things in
| banking. Most accounting/finance departments are ok with
| rounding pennies every month.
|
| I run a Commercial Real Estate Servicing platform, where we
| are accruing interest on large balances daily. Our method is
| to not do the rounding daily, but add up all the numbers for
| a given period, say a month, and then round to the penny and
| create a single adjustment rounding transaction along with
| it. Accounting departments love us for it.
|
| If we rounded daily before storing the amount, the adjustment
| for accounting is usually a few pennies at least every month
| they have to make. Our method, it's roughly $0.01 per year
| with monthly periods, adjusted usually at the very end. Which
| on a $20MM loan, is very well within the bounds of
| acceptable.
| _glass wrote:
| I love how small details, like rounding always up for 2.50
| would be significantly skewing the numbers to the higher
| values, so there are functions like ROUND_HALF_EVEN that
| would round up on even numbers, and down on uneven ones.
| hef19898 wrote:
| The real reason is because Cathrine Zeta Jones and James
| Bond actually _did_ implement a program in Malaysia that
| collects all those rounding errors on a seperate bank
| account. And since it wenr global, affecting everypne,
| everyone thinks it ia simply normal.
|
| Or it is because rounding errors happen and accounting is a
| bitch. The first option makes for a better movie plot so.
| dahart wrote:
| I guess I'm old because I credit that plot to Superman
| III. TIL it's called Salami Slicing
| https://en.wikipedia.org/wiki/Salami_slicing_tactics#
| CleaveIt2Beaver wrote:
| Man, you and I remember Office Space differently! /s
| pdntspa wrote:
| Yeah. I worked on a lending platform that used floats
| (!!!), and their response when I brought this up was that
| as long as the result is within something like $10, it was
| not an issue.
|
| I brought up specific math problems that floats couldn't
| handle and they weren't phased
| Aardwolf wrote:
| Would IEEE decimal128 be sufficient (instead of arbitrary
| precision)?
|
| "Formally introduced in IEEE 754-2008, it is intended for
| applications where it is necessary to emulate decimal rounding
| exactly, such as financial and tax computations."
|
| https://en.wikipedia.org/wiki/Decimal128_floating-point_form...
| [deleted]
| onetimeuse92304 wrote:
| Hypothetical solutions that do not exist are none of my
| concern.
|
| Did you know different countries and different currencies
| have different rounding rules, for example for tax-related
| calculations? Does "IEEE decimal128" support this? Unless you
| can get all countries on our planet to agree on a single
| standard, any solution that does not allow specifying
| rounding rules is pretty much useless (unless you want to
| implement rounding yourself which tends to be very tricky --
| I know because I attempted this couple of times).
| Aardwolf wrote:
| What do you mean by hypothetical solution that does not
| exist? This is actually specified.
|
| IEEE does specify multiple rounding modes. Does it make
| more sense to use an existing spec, or roll your own
| numeric library with rounding modes?
| jkestner wrote:
| I'm going through this pain right now in helping my kid
| with homework in rounding and discovering my internalized
| rules are different from what they're being taught now.
| EXACT same pain as yours, depending on the precision and
| rounding rules of your pain scale.
| ilyt wrote:
| Well you did turn your hypothetical ignorance into
| practical one, I got calculator using it... actual physical
| object.
| eesmith wrote:
| This is not hypothetical.
|
| Yes, of course IEEE decimal supports setting the rounding
| mode. The authors of the spec aren't ignorant of what's
| needed for financial and tax computations.
|
| Use fe_dec_setround from ISO/IEC TR 24732, "Extension for
| the programming language C to support decimal floating-
| point arithmetic".
|
| The modes listed at
| https://www.ibm.com/docs/en/zos/2.5.0?topic=functions-fe-
| dec... are: FE_DEC_DOWNWARD rounds
| towards minus infinity FE_DEC_TONEAREST
| rounds to nearest FE_DEC_TOWARDZERO rounds
| toward zero FE_DEC_UPWARD rounds toward plus
| infinity FE_DEC_TONEARESTFROMZERO rounds to
| nearest, ties away from zero _FE_DEC_AWAYFROMZERO
| rounds away from zero _FE_DEC_TONEARESTTOWARDZERO
| rounds to nearest, ties toward zero
| _FE_DEC_PREPAREFORSHORTER rounds to prepare for
| shorter precision
| Aardwolf wrote:
| This list seems to be missing something since afaik, IEEE
| floating point also specifies round-to-even (bankers'
| rounding) for round to nearest ties. Unless
| 'FE_DEC_TONEAREST' is that, the documentation does not
| say.
|
| https://en.wikipedia.org/wiki/IEEE_754#Roundings_to_neare
| st
|
| EDIT: apparently IEEE does not specify a "round-to-odd"
| for ties despite this having been used for banking in the
| UK :/
|
| https://en.wikipedia.org/wiki/Rounding#Rounding_half_to_o
| dd
| jaclaz wrote:
| The authors of the spec made some provisions, and very
| likely all of them are useful and correct, the issue is
| how the programmers will use them, and in some cases
| there isn't even a "correct" solution that everyone uses.
|
| A classic example in invoicing is an item that is
| advertised for 60.00 (to the final user) VAT 10%
| included.
|
| If you try making an invoice for that sum in a few
| programs you will find three or four way it is
| implemented.
|
| Some will have 54.54+5.45=59.99, some will have
| 54.54+5.46=60.00, some will have 54.55+5.46=60.01 (and
| possibly a "discount" of 0.01), some will have
| 54.545+5.45=60.00, some will have 54.54545454+5.45=60,00.
| eesmith wrote:
| Yes, it isn't possible for the software to know your
| local accounting laws and practices.
|
| My point is it's probably better to use existing, well-
| tested provisions than to build your own from scaled
| integers, to get one of those three results.
|
| As a bonus, you might get hardware support in the future.
| jaclaz wrote:
| Yes, I understand what you are saying, I was highlighting
| that those (if adopted) would only fix (maybe) part of
| the problem, they are just (better) tools.
|
| At the end of the day what I want (and I presume any
| other customer wants) is a correct invoice with the
| correct net, tax and total, and this will only happen
| when (if) the programmer understands the base issues and
| uses the correct library/algorithm/whatever.
| magicalhippo wrote:
| For goods items, Danish customs require specifying 3
| decimals for weights under 1kg, otherwise no decimals.
| Off the top of my head I don't recall exactly how they
| expect rounding to be done, I'd guess towards infinity.
|
| Many duties are calculated based on net weight, and often
| the net weight per goods line is the result of a
| calculation, for example you're importing N items with a
| per-item weight of X. If you have a large number of goods
| items above 1kg but less than 10kg that has weight-based
| duties, the rounding mode can matter a lot.
|
| None of the rounding modes mentioned captures this
| below/above 1kg split, so you have to do this in code
| anyway. Might as well do the rounding there too, to be
| sure some injected code doesn't mess up the expected
| rounding mode or similar[1].
|
| [1]: https://irrlicht.sourceforge.io/forum/viewtopic.php?
| t=8773
| eesmith wrote:
| Sure, you'll need to handle special cases yourself. But
| perhaps you don't have to handle all the cases yourself?
|
| As I understand it, one of the new things in IEEE 754 is
| the idea of a "context", which stores this information.
| This can be global, but does not need to be. With
| Python's decimal module it is a thread-local variable.
|
| If you are concerned about, say, mixing thread-local and
| async, you can also use context methods directly, like:
| >>> import decimal >>> x =
| decimal.Decimal("54.1234") >>> y =
| decimal.Decimal("987.340") >>> x+y
| Decimal('1041.4634') >>> decimal.getcontext()
| Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999,
| Emax=999999, capitals=1, clamp=0, flags=[],
| traps=[InvalidOperation, DivisionByZero, Overflow])
| >>> >>> c1 = decimal.Context(prec=4) >>>
| c1.add(x, y) Decimal('1041') >>> c2 =
| decimal.Context(prec=5) >>> c2.add(x, y)
| Decimal('1041.5') >>> c3 = decimal.Context(prec=5,
| rounding=decimal.ROUND_DOWN) >>> c3.add(x, y)
| Decimal('1041.4')
|
| I don't know what the C or C++ API proposals are.
| rbatiati wrote:
| Rounding monetary values is a complex, opinionated and
| business-defined operation. Sometimes it's even orthogonal to
| the datatype used.
|
| Things get out of hand when you need to round multiple
| different things that have to sum up at the end.
|
| For example:
|
| - Items in an invoice are rounded and summed. (eg. $1.1234 *
| 5.678kg)
|
| - Payments of an invoice can be paid in multiple installments,
| with interests that are also rounded (eg. 1.77% per month).
|
| - The value paid of interest *per item* must match the total
| value paid of interest in all installments of all invoices in
| the same period.
| tantalor wrote:
| Serialization as a byte string ought be good enough if the
| storage layer doesn't support arbitrary precision natively.
| RamblingCTO wrote:
| Not sure about that. In Germany, especially SMEs, no one cares
| about cents. Your tax reports are done in rounded Euros anyway.
| People, companies, and the taxation and financial state dept.
| are well aware of rounding issues, different ways to round that
| no one really cares about cents.
|
| Besides that, using BigDecimal with two decimal places is
| sufficient in the java world imho. Depends on your use case.
| I'm entirely sceptical of people claiming general things.
| Depends on the requirements I'd say.
| blibble wrote:
| they'd probably care if you're compounding interest daily on
| that rounded up euro
| t0mas88 wrote:
| Same in the Netherlands. There is an official rule that you
| don't have to do mathematical rounding to get to whole
| euro's, you can do it in whichever direction is more
| favourable to you. That rule is probably there just to save
| the tax services some extra work and IT costs.
| lxgr wrote:
| Only final values are rounded to full Euros (down, if I
| remember correctly).
|
| If a large taxpayer starts rounding down as part of
| intermediate calculations of their tax liability, I think
| they'd get some questions.
|
| But yes, rounding does happen a lot - what's important is
| that everybody uses the same, transparent rules for that, or
| it becomes impossible to double-check somebody's books, tax
| declaration, invoice etc.
| RamblingCTO wrote:
| Well, how much money can you save by efficient rounding?
| Surely not that much that anyone would bother. There's a
| thing called "Kaufmannisches Runden", which is kind of
| cheating as well.
|
| > But yes, rounding does happen a lot - what's important is
| that everybody uses the same, transparent rules for that,
| or it becomes impossible to double-check somebody's books,
| tax declaration, invoice etc.
|
| They don't, that's why it doesn't matter that much ;)
| lxgr wrote:
| > Well, how much money can you save by efficient
| rounding?
|
| You and me? Probably a few cents.
|
| A bank or a large corporation selling things billed in
| sub-cent amounts? Single-digit percentages of their gross
| revenue, i.e. many millions.
|
| Just as a very simple example: I'm your bank/phone
| provider/..., and I'm charging you a flat fee of 1.9
| cents per transaction/call/... You're my customer and
| make a billion of such transactions per year.
|
| Option 1: 1000000000 * 0.019 = 19000, you owe me
| $19000000.
|
| Option 2: There are no fractional cents, so let's just
| round up each individual billing event. 1000000000 * 0.02
| = 20000000, you owe me $20000000. Cool, a free extra
| million for the company!
|
| This is why these things are precisely regulated when it
| comes to sales tax/VAT, for example.
|
| > There's a thing called "Kaufmannisches Runden", which
| is kind of cheating as well.
|
| Always depends on which side you're on. If you're getting
| a refund, it can work in your favor! Importantly, it's a
| precisely defined rule so that it's not possible to
| _cheat in the implementation_.
| [deleted]
| weinzierl wrote:
| _" For accounting you should only ever use arbitrary precision
| math library"_
|
| I'm a bit surprised by this advice. I thought the common wisdom
| was to use a decimal type like BigDecimal in Java.
| c2h5oh wrote:
| BitInteger and BigDecimal are arbitrary precision types in
| Java
| cwmma wrote:
| BigDecimal is an arbitrary precision type so using BigDecimal
| is how you would follow said advice in Java.
| throe37848 wrote:
| You need to be also handle "origin" or "flavour" of money. Future
| governments may place various sanctions and limitation on money.
| So green dollars will be better, Russian dollars not so great and
| so on. Some money may be owed to local VIP, and should not be
| confiscated... All that may be mixed on single bank account.
| jorangreef wrote:
| Yes, we do also have various user_data fields for
| accounts/transactions to record the: who / when
| / where / why / what / how / how much
|
| https://docs.tigerbeetle.com/reference/transfers
| matt3210 wrote:
| At some point denominations will be 2^20 USD per note. As
| inflation grows, in the USA and others, a 64bit won't be enough.
| Money is imaginary store of value we all agree on. The actual
| number changes.
| mbg721 wrote:
| Wouldn't we just re-base the currency at that point?
| jon-wood wrote:
| That "just" is doing some very heavy lifting. That could
| potentially involve having to update almost every financial
| system worldwide given the US dollar's position as a global
| reserve currency.
| ben_w wrote:
| If inflation averages 5% per year, a factor of 10^17 (what
| are the biggest USD notes actually in use?) is just over
| 800 years away, which is far enough that we might
| legitimately not have a moon any more let alone dollars.
|
| If hyperinflation brings that date closer, the dollar will
| probably also stop being a global reserve. Or possibly:
| will be caused by it ceasing to be a global reserve.
| Izkata wrote:
| The federal reserve aims for 2% a year, their adjustments
| just haven't been working.
| feoren wrote:
| > 800 years away, which is far enough that we might
| legitimately not have a moon any more
|
| Wait, what? 800 years is absolute peanuts for the fate of
| orbital bodies. Wikipedia's Timeline of the Far Future
| estimates the demise of the moon in 7.59 billion years;
| still in orbit around the Earth (albeit a much higher
| one), it gets destabilized by the expanding sun and
| eventually swallowed by it, along with the Earth. If they
| aren't swallowed by the sun, they estimate 65 billion
| years before we lose the moon in one way or another.
|
| https://en.wikipedia.org/wiki/Timeline_of_the_far_future
| ben_w wrote:
| https://en.wikipedia.org/wiki/Self-replicating_spacecraft
|
| Even the unit of replication is a factory under human
| control with no novel AI, and which can only replicate
| with significant human oversight of already existing
| mining, processing, and manufacturing equipment, it
| doesn't take insane reproduction rates to disassemble the
| moon in 800 years.
| feoren wrote:
| That's like saying "5 years away is far enough that Mount
| Rushmore might be gone by then!" because we could nuke it
| if we wanted to. _Why_ would we do that!? We like the
| moon being there! Do these examples really help
| illustrate how far away 800 years, or 5 years, are?
| ben_w wrote:
| Lots of people want to build megastructures, and the moon
| is convenient material; I suspect that when the
| capabilities make it seem like a serious possibility,
| people will discover the problems and then do it anyway
| just like with almost all the other environmental issues
| to date that compete against economic interests.
|
| However, the main point of the example is "800 years is
| too far ahead to plan for how much the US dollar might
| inflate" by way of demonstrating how extreme things can
| change. As far as I know, no fiat currency has existed
| that long, and only three country-like entities[0].
|
| Mount Rushmore isn't likely to be targeted by nukes, but
| I strongly suspect that it is defended against vandals
| (politically motivated or otherwise) with dynamite (or
| similar categories of explosives) -- that said, if you've
| always wanted to go and have not yet done so, you should,
| as I could've said much the same thing about the World
| Trade Centre 22 years and a fortnight ago.
|
| (I wonder if a _single_ unfriendly nuke on US soil would
| cause an economic shock? Normally the assumption would be
| what else might come with it).
|
| [0] https://www.brainscape.com/academy/longest-lasting-
| empires-w...
| badcppdev wrote:
| I love how you're bringing the US dollar's reserve currency
| status into a hypothetical where the US Treasury is issuing
| million dollar denominations. We can assume that some other
| parts of the world's financial system will have required
| fixing first.
| mbg721 wrote:
| Yes, but I think a "new dollar" is more likely than the US
| putting up with million-dollar bills. I guess it's a tough
| call which one is more embarrassing.
| weinzierl wrote:
| I once argued for using BigDecimal instead of Doubles in an
| invoicing software but had a hard time to come up with a
| practically relevant example.
|
| Is there an example where it makes a noticeable difference (at
| least one cent in the final result) that does not involve
| unrealistic amounts or numbers of items?
|
| I'm not arguing for Doubles, just collecting arguments to
| convince.
| dvlsg wrote:
| Technically you can have noticeable differences before you even
| make it to 1 cent. For example, if you're trying to determine
| if a result of a calculation is negative, 0, or positive for
| whatever reason. With floats/doubles, you would probably need
| to consider "0" to actually be "a number sufficiently close to
| 0, if not 0 exactly" and then remember to handle that
| everywhere.
|
| It can also be noticeable if you're just trying to calculate
| something like "is the invoice paid off". Maybe your view layer
| is showing $0.00 balance to the end user, but the backend
| hasn't correctly rounded off those extra bits from a floating
| point calculation, so your backend logic is now saying the
| invoice is not actually fully paid off, even if the end user
| has no idea what they could possibly still owe.
| crazygringo wrote:
| I'm curious about this too. If you were engaged in millions of
| arithmetic operations then I can see how inaccuracies might
| accumulate in theory, but in practice floating point operations
| are intentionally designed to minimize that.
|
| And for everyday individual transactions it's hard to see a
| problem. Maybe the problem is more when you're summing up every
| single financial transaction for the year? But even in that
| case, if the smallest financial resolution is a cent, all the
| floating point noise seems like it would be occurring many
| decimal points beyond. Even if you're dealing with billions of
| dollars.
|
| To be clear, I wouldn't do it myself -- I'm too risk-averse,
| too afraid of unknown unknowns. But it is hard to see what
| actual real-life negative consequences there would be for 99.9%
| of businesses, unless I'm missing something? Like the parent
| commenter, I'm looking for where I'm wrong here.
| bob1029 wrote:
| The part of using float for this that concerns me is not
| epsilon. It is all of the other weird edge cases & states. I
| don't like that 2 flavors of infinity and something that
| isn't a number are explicitly representable.
| a-french-anon wrote:
| Reminds me of the Rosetta page
| https://www.rosettacode.org/wiki/Currency for various ways to
| handle a related problem.
| netheril96 wrote:
| ETH uses 256-bit integers for accounting.
| karg_kult wrote:
| [flagged]
| lnxg33k1 wrote:
| We could also tax everything above 32 bits, good for people, good
| for machine
| jkestner wrote:
| Imagine if the most money you could have is $43 million
| (rounding!), and it rolled over to 0 if you exceeded that.
| You'd be paying accountants to keep you as close to the limit
| as you dare, instead of just cheating on taxes. But not paying
| them too much, as you're only a multimillionaire.
| undersuit wrote:
| I guess at some point you just hire accountants to throw mini
| basketballs at mini hoops. Most efficient way to keep you
| below $43 million.
| lnxg33k1 wrote:
| The real trickle down
| [deleted]
| Waterluvian wrote:
| I'm a bit surprised that these two concepts are seen together.
| I'd of thought that financial math and data management would
| always be done with some level of abstraction so it doesn't
| matter at all what your computer's implementation is.
|
| Then again, 128 bits is plenty for microcents or whatever the
| minimim unit is.
|
| I'm guessing back in the day when things were 32 bit or less,
| there were entire financial database implementations that handled
| this abstraction?
| dahfizz wrote:
| > be done with some level of abstraction so it doesn't matter
| at all what your computer's implementation is.
|
| This still doesn't do that, its just integer math. It doesn't
| matter how your CPU implements it, as long as `x = a + b` gives
| the correct value for x.
|
| You don't have to immediately reach for an abstraction layer
| when you hear the word "bits" ;)
| Waterluvian wrote:
| But without a sufficient stratigraphy of abstractions, I
| can't ever dig down if I run into issues! ;)
| dboreham wrote:
| Handled in hardware on some machines (e.g. VAX)
| DamonHD wrote:
| If you actually want to do something useful and accurate and
| auditable and performant and space-efficient, because you have
| a lot of money values to bank with, you really don't want too
| much abstraction.
|
| My experiences in various bits of banking include where juniors
| ignore advice NOT to store currency in floating point values
| and then come whining that arithmetic is broken, and tech dudes
| in a lab deciding that every single FX flow in an investment
| bank should have 2MB of (unshared) calendar hidden inside its
| abstraction which made some individual trades too big to load
| even for powerful machines...
|
| Fixed point calcs in integers are good.
| Waterluvian wrote:
| Floating point feels like an incredibly grokkable concept
| that was just not taught well for a long time. Maybe too
| mathematically (of course). Or maybe that was just my
| experience.
|
| I feel like any dev team should pick up a copy of this for
| on-boarding: https://jvns.ca/blog/2023/06/23/new-zine--how-
| integers-and-f...
| fidotron wrote:
| Floating point being grokkable doesn't make it any more
| suitable for this application.
|
| Floating point is inherently an approximation - your bank
| balance should not be an approximation.
| Spivak wrote:
| > Floating point is inherently an approximation - your
| bank balance should not be an approximation.
|
| I think this is a perfect example of bad floating point
| teaching. Floating point is not an approximation in any
| sense. If the numerical result of your calculation is
| representable in floating point you will get an exact
| answer always. And for results that aren't representable
| you decide exactly what should be done about that. It's
| like saying integers are an approximation because 5/2 ==
| 2.
| dahfizz wrote:
| In programming, an `int` perfectly represents the
| integers between INT_MIN and INT_MAX.
|
| A `float` on the other hand, approximates the real
| numbers. It can perfectly represent exactly 0% of them.
|
| Having control over the rounding behavior is meaningless
| - floats cannot correctly represent any non-contrived
| calculation. Exact representation is important in
| financial systems.
| fidotron wrote:
| TBF, be careful here. The IEEE floats can represent a
| subset of integers in their range exactly. For example,
| 64 bit floats can represent the range of 32 bit ints
| accurately (and more).
|
| That said, it is bizarre to claim that if the result can
| be represented you get the exact result, when the core
| problem is that the result cannot be represented because
| the representation is an approximation.
| dahfizz wrote:
| > The IEEE floats can represent a subset of integers in
| their range exactly. For example, 64 bit floats can
| represent the range of 32 bit ints accurately (and more).
|
| I know, I am being a little facetious. A double has a 52
| bit mantissa, so it can exactly represent integers that
| need 52 or less bits.
|
| Still, as a percent, a float can represent 0% of the
| reals. There are an infinite amount of numbers it cannot
| represent, even if we give it lower and upper bounds.
| Whereas an int can represent 100% of the integers within
| a lower and upper bound.
| Spivak wrote:
| > floats cannot correctly represent any non-contrived
| calculation
|
| Like adjusting all your financial calculations to use
| microcents and partitoning instead of division to keep
| the result representable by integers? Neither can
| represent 1/3 even shifted. When you want to do exact
| calculations with floats, and you can, you just have to
| set yourself up so that the result is exactly
| representable, it's not as intractable as you make it
| seem.
|
| > A `float` on the other hand, approximates the real
| numbers
|
| Okay so that's not at all what they do, they represent
| subsets of the reals, just like how integers represent a
| subset of the reals. Even arbitrary precision libraries
| can only represent a subset of the rationals.
| dahfizz wrote:
| > they represent subsets of the reals
|
| Sure. My point is that this subset is useless. Because
| trying to add, subtract, multiply, or divide members of
| this set will result in a number outside the set.
|
| > When you want to do exact calculations with floats, and
| you can, you just have to set yourself up so that the
| result is exactly representable, it's not as intractable
| as you make it seem.
|
| In the general case, you absolutely cannot. Lets look at
| some examples.
|
| In forex trading, you need 9 digits after the decimal
| place in the price. So right off the bat, a valid price
| like 1000000.000000001 cannot be represented by a float.
| If the exchange sends your system that price, your system
| is guaranteed to be wrong.
|
| Lets say you start at a representable price, like
| 1000000.0 and want to tick it up or down by the tick
| size, say 0.025 . The result of that addition /
| subtraction is not representable, so you cannot calculate
| and round prices correctly.
|
| If you don't have control of your inputs, and you need
| precision, floats will never work.
| Spivak wrote:
| I think you're getting the impression that my stance is
| "floats are usable for all problem domains" when it's
| really "floating point arithmetic is not the same as
| approximate calculations."
|
| Nearly all mathematical calculations cause the result to
| be outside the range of integers. You can't do much else
| other than subtract without accounting for edge cases. No
| matter what tool you use you must work with your chosen
| representation and around its limitations and make sure
| your domain can be modeled exactly. For example Python's
| base random function chooses a floating point uniformly
| in the range [0, 1) but it achieves this by requiring
| that the result be a multiple of 2^-52 which is exactly
| representable so rounding doesn't introduce bias.
|
| > If you don't have control of your inputs
|
| Well you clearly do to some degree because you're sure
| you can model anything you might might receive with fixed
| sized fixed precision integers. I'm not saying this means
| you can just switch to floats but that you're doing the
| same thing, mapping the real life problem domain exactly
| to a subset of the reals that is closed under the
| operations you want to perform.
| fidotron wrote:
| > When you want to do exact calculations with floats, and
| you can, you just have to set yourself up so that the
| result is exactly representable, it's not as intractable
| as you make it seem.
|
| Can you expand on what you mean by that? Whenever I have
| dealt with calculation errors (either in fixed or
| floating point) "set yourself up so that the result is
| exactly representable" has been the key problem to
| prevent errors accumulating.
|
| I obviously disagree on some other points, but circular
| discussions go nowhere!
|
| Edit to add: Essentially I'm fishing for tactics. A big
| one in graphics development is detailed here:
| https://developer.nvidia.com/content/depth-precision-
| visuali... - but in fixed point I got very used to
| working out how to premultiply variables depending on
| their expected ranges.
| [deleted]
| Waterluvian wrote:
| Indeed. I'm just making a tangential comment. Definitely
| want to work in unsigned fractional cents.
| DamonHD wrote:
| More to the point binary fp absolutely is a _bad_
| approximation to, and does poor arithmetic on, common
| legal sub-1 decimal currency values, ie those that do not
| have an exact binary fp representation.
| shortrounddev2 wrote:
| > I'm guessing back in the day when things were 32 bit or less,
| there were entire financial database implementations that
| handled this abstraction?
|
| This issue is what COBOL was designed to solve. Fixed decimal
| point arithmetic in base 10
| Etheryte wrote:
| Perhaps I'm the odd one out here, but most financial systems I've
| had the chance to work with don't actually use numeric types to
| store values, they use strings or other comparable types. Numeric
| values are passed to all outside interfaces, but the internal
| states are written in a way where no bit level issues peddle with
| the values. I'm wondering what the experience of the wider
| audience here is?
| alexvitkov wrote:
| If by "bit-level issues" you mean bit flips (which you should
| be worried about), a string doesn't help much - "4" is 0x34
| ASCII/UTF-8, flip lowest bit and you get "5" (0x35).
|
| I'd imagine if I have to protect against bit-level fuckery
| something like this would be a better representation:
| struct Dough { u64 amount; u64
| amount_again; u64 amount_just_to_be_really_sure;
| }
|
| that and hardware-level protection of course
| marcosdumay wrote:
| That's the kind of thing for what error correction codes were
| invented.
| rvnx wrote:
| Storing the same element the same way isn't really helping
| against implementation bugs, if going that route, better
| store in multiple formats (u64, int, or string), to protect
| yourself from a CPU or interpreter or library bug. In
| practice, just store the amounts as integer, and if you are
| really worried, add a checksum (if total balance is not
| enough).
| DamonHD wrote:
| That pretty much _guarantees_ being the victim of multiple
| coding bugs...
| alexvitkov wrote:
| Maybe, if you're an incredibly bad programmer. Add
| operator overloading and method to extract the number and
| you never have look at the internals again.
| GTP wrote:
| I think what OP's talking about aren't sw bugs, but rather
| hw errors like a bit flip caused by an external
| interference.
| Izkata wrote:
| They're talking about floating point precision issues, same
| thing as the article, and explaining another way to deal with
| it that doesn't require thinking as low-level as bits like
| the article is mainly talking about.
| paxys wrote:
| The financial systems you've used never needed to add two
| numbers together?
| wyldfire wrote:
| > internal states are written in a way where no bit level
| issues peddle with the values
|
| ... "bit level issues"? you eventually are going to need to use
| those bits to add, multiply, subtract or divide the numbers.
|
| Using character strings to represent numbers is certainly one
| way to do arbitrary precision/ BigInteger (like the article
| describes). But you might want to postpone transcoding it to
| characters until you decide to export your numbers across a
| boundary. Otherwise all of the arithmetic operations you do
| have to suffer this round trip each time.
| dahfizz wrote:
| A shocking number of devs are simply afraid of bits and
| bytes.
| alentred wrote:
| Oh, this does sound odd indeed. I can only assume this is very
| slow, and voluminous on the storage side.
|
| In a similar vein, the only "tricky" solution I saw once was a
| financial system that stored rational numbers as fractions, and
| used fractions for all computations too. A decimal point was
| only used for the final results (end-user UI, APIs, etc.). I
| still think it was a an overkill.
| kawhah wrote:
| Interesting, were the denominators always powers of 10? Or
| any positive integer?
| dahfizz wrote:
| Sounds slow as hell, what kind of financial systems have you
| worked with? I write trading software, and pretty much everyone
| uses integers with implied decimal place, similar to TFA.
|
| How do you know you convert your internal string to a float/int
| correctly? You have to deal with the numeric types eventually
| tombert wrote:
| I've never written any trading software, but out of
| curiosity, have you done any tests comparing something like a
| GMP arbitrary-precision number vs a raw integer type.
|
| Obviously the raw integer (64 bit or 128 bit) will go faster
| since it would have CPU-level assistance, but I'm curious to
| what that actually ends up being in practice, especially at
| the scale of trading. Is it 10% faster? 10X faster? Somewhere
| in between?
| DamonHD wrote:
| Not true for any of the finanical systems I've worked for the
| credit/derivatives/FI/etc desks of some of the largest
| investment banks down to the systems for the virtual card
| e-money issuer in the UK that I founded.
| rvnx wrote:
| They use integers to store cents or fraction of cents, and
| that's it (or the equivalent of MySQL "DECIMAL" format if not
| using integers)
| DamonHD wrote:
| When you say "they" I could tell you exactly what format we
| stored card balances in, including the implied point
| position for different currencies (not the same for GBP and
| (say) JPY) and none of it involved DECIMAL!
| rvnx wrote:
| > They use integers to store cents or fraction of cents
| or DECIMAL as alternative if not using integers
|
| Seemed rather clear, what's difference with what you say
| ?
| DamonHD wrote:
| I referred to 'they' for my clients and start-up. You
| seemed to be making claims about those particular
| implementions, which seemed a bit odd.
| fancyfredbot wrote:
| Derivatives are generally subject to some fairly large
| uncertainty in valuation, for example bid/offer spreads are
| usually many orders of magnitude larger than floating point
| error. When the derivative expires it does have some very
| fixed value but the investment bank will have made enough
| money off the trade to "generously" round up the float to the
| nearest cent.
| kawhah wrote:
| I have never encountered such a system. Integers used for
| fixed-point representation do not suffer from "bit-level
| issues".
| amadvance wrote:
| Is fixed-point the right term ?
|
| As far as I know fixed point numbers have a fixed fractional
| part in bits, but this is different from using integers with
| a multiplicative factor, like 100, to represent correctly a
| fractional part as 1/100.
| tech_ken wrote:
| >Surprisingly, we also don't use negative numbers (you may have
| encountered software ledgers that store only a single
| positive/negative balance). Instead, we keep two separate
| strictly positive integer amounts: one for debits and another for
| credits.
|
| It's funny I've always thought of two-column bookkeeping as a
| kludge that was invented because the author was unaware of
| negative numbers. But here there's actually a justifiable
| technical reason why they're superior (in this specific context)!
| History is a silly thing
| LAC-Tech wrote:
| This is also the way to do it if you want a number that
| multiple nodes can edit independently.
|
| When you sync back up, do a big tally at the end, and that's
| your final number.
|
| (This constitutes a CRDT, and is known as the Positive/Negative
| Counter).
| tech_ken wrote:
| The idea is similar/equivalent to a stack of git deltas yeah?
| Each line is a change of one of two types and then you
| combine them to get a net change?
| LAC-Tech wrote:
| I'm actually not too familiar with git deltas, but that
| does sound very similar to an Observed/Removed Set, another
| CRDT.
| thetwentyone wrote:
| Reference for the "justifiable technical reason"?
| tech_ken wrote:
| I'm referring to the OP which discussed the technical
| justification for their choice. An employee from the firm
| also elaborated a little more elsewhere in the replies
| fragmede wrote:
| Accounting for computer scientists* is a good read if you've
| got some interesting in accounting (and have a CS background)
| and are wondering why accounting is just so danged complex.
|
| * https://martin.kleppmann.com/2011/03/07/accounting-for-
| compu...
| tech_ken wrote:
| Oh I'm familiar B)
|
| Used to use this CLI tool "ledger" to keep the books for a
| small nonprofit I was treasurer-ing for. Awesome tool, and
| (in conjunction with this read and a few others) it taught me
| a ton about all that good GAAP stuff
| Jabrov wrote:
| How are they superior though? What do they gain by doing this
| (other than added complexity)?
| jorangreef wrote:
| Hey! Joran from TigerBeetle here.
|
| (I know this only because I somehow happened to major in
| Accounting back in university), but when you represent a
| general ledger of accounts, there are always two positive
| columns for amounts in any given account, one for debits, the
| other for credits.
|
| The golden rule is that you always add to either column. You
| always preserve information.
|
| To see why two columns (or two integer balances) preserves
| more information, take this example: 1. An
| account A with a debit balance of $1m and a credit balance of
| $1m, and 2. An account B with a debit balance of $0 and
| a credit balance of $0.
|
| Account A contains volume information in that you can
| immediately see not only that account A was transacted
| against, but with significant amounts. Conversely, account B
| shows no volume. But it's also clear even that there were no
| transactions between A or B.
|
| Whereas, if you take the net of the two amounts, and reduce
| that to a single amount in storage (as opposed to only taking
| the net in presentation), and if you use negative numbers,
| you lose this information. It's a subtle thing.
|
| The other angle here, is to consider why some engineers
| shortcut to negative numbers in the first place. I find that
| it's usually because they haven't fully grokked that
| accounting is itself a type system. You get assets,
| liabilities, equity, income and expenses (as account types),
| and the debit/credit balances, when considering the type of
| an account, tell you further information. For example, did a
| bank account suddenly transition into overdraft? Different
| account types, increase on different sides.
|
| I think this is also the reason that you find accountants
| typically wrapping amounts in parentheses, and then
| specifying the DR or CR side (or type of account), rather
| than using a negative sign. It's a tradition of preserving
| information.
| munificent wrote:
| _> You always preserve information._
|
| Using two positive numbers preserves _some_ information,
| but still destroys plenty. Just less than a single signed
| number would. Consider two accounts: 1.
| An account A with a debit balance of $1m and a credit
| balance of $0, and 2. An account B with a debit
| balance of $1m and a credit balance of $0.
|
| One of those was opened by a lottery winner last week who
| did a single transaction dropping in their winnings. The
| other was opened by a retiree 60 years ago who has been
| dripping small deposits in for their entire working
| history. Which is which?
|
| That distinction is still lost by summing debits and summit
| credits.
|
| To really preserve information, you'd need the full list of
| all transactions. But, obviously, that comes at a
| significant performance cost. So the way to look at storing
| sums for debits and credits is that it's a trade-off which
| gives you a little more information than just a single
| balance but is still a relatively small fixed-size amount
| of data.
| kardianos wrote:
| It sounds like they use a rational number with a fixed power of
| 10 denominator. Much like if they used Go's *big.Rat type with a
| fixed denominator of say 100 or 100000 depending on the currency,
| then the numerator they are moving from a 64 integer to a 128 bit
| integer.
|
| I personally don't see the advantage this has over a decimal 128
| numeric value. In either situation, if you have 10 / 3, you will
| get 3.33 and need to round. Ultimately, the math concepts in
| finance are different then in abstract math. If for some reason
| you need to divide $10 by 3, it should result in three numbers:
| 3.33, 3.33, and 3.34.
|
| But fundamentally, I don't see how their fixed integer math fixes
| something as fundamental as that, over a standard decimal 128
| representation.
| rbatiati wrote:
| > If for some reason you need to divide $10 by 3, it should
| result in three numbers: 3.33, 3.33, and 3.34
|
| Exactly! We don't try to "fix this math problem"; instead, we
| just want to reduce the surface area by using plain integers
| instead of decimal floating points.
| mk_stjames wrote:
| "All right, so when the subroutine compounds the interest, it
| uses all these extra decimal places that just get rounded off. So
| we simplified the whole thing and we just... we round them all
| down and just drop the remainder... into an account that we
| opened."
| jorangreef wrote:
| Glad you enjoyed the reference!
| throw0101c wrote:
| I was under the impression that BCD was generally recommended for
| money, often because of (IEEE?) rounding and machine
| precision/epsilon:
|
| * https://en.wikipedia.org/wiki/Binary-coded_decimal
|
| * https://en.wikipedia.org/wiki/Machine_epsilon
| dahfizz wrote:
| BCD is _better_ than IEEE 754 floating point, but simple
| integers with an implied decimal point is much better than
| either of those.
| RetroTechie wrote:
| BCD makes stored value -> human-readable trivial, at the cost
| of complicating math on those values.
|
| So it's useful for applications where you're mostly doing
| human input/output <-> stored value.
|
| But as soon as you do any non-trivial math on those values,
| using (fixed point?) integers wins. At the cost of a simple
| stored value <-> human readable conversion.
|
| I'd think most financial applications fall into the category
| "do math, so integers win over BCD".
| kardianos wrote:
| I honestly don't understand the argument here or the parent
| comment makes.
|
| Why is a BCD decimal 128 worse at math then a fixed point
| integer? You are saying it is more CPU efficient? Are you
| saying some operations with fixed point integer math
| operations are more accurate then dec128?
|
| I've seen this asserted several times, both in the post and
| in comments, but I've never seen a single concrete example
| of it being better. Can someone provide an example?
| devit wrote:
| Most CPUs don't have BCD math instructions, so you need
| multiple instructions, with probably around a 10-100x
| slowdown in math.
| Sohcahtoa82 wrote:
| Do you know what BCD is? If you did, it becomes pretty
| obvious why BCD is significantly slower than fixed point
| integers.
| zamalek wrote:
| While IEEE 754 does have curiosities, the 1/10 problem the
| article points out isn't really addressed by anything
| mentioned in the article (or here). BCDs have exactly the
| same problem with e.g. 1/3.
|
| What you really want is a rational (fractional value:
| numerator and denominator) of some form.
| eesmith wrote:
| I'm under the impression that people use decimal floats from
| IEEE 754-2008, which is Crenshaw's General Decimal Arithmetic
| at https://speleotrove.com/decimal/decarith.html .
|
| As I understand it, the regulations related to money can
| require specific rounding modes and a specific number of digits
| for intermediate representations. These are much easier to
| manage with, eg, Python's decimal module than doing everything
| as integers.
|
| For example, at https://news.ycombinator.com/item?id=36687627 I
| pointed to US law at
| https://www.law.cornell.edu/cfr/text/7/1005.83 with:
| (3) Divide the result in paragraph (a)(2) of this section by
| 5.5, and round down to three decimal places to compute
| the fuel cost adjustment factor; (4) Add the result
| in paragraph (a)(3) of this section to $1.91; (5)
| Divide the result in paragraph (a)(4) of this section by 480;
| (6) Round the result in paragraph (a)(5) of this section down
| to five decimal places to compute the mileage rate.
| yyyk wrote:
| Every financial system I've seen uses either decimal floating
| point or integers. Using normal float is just asking for
| trouble.
| fer wrote:
| I've seen floats for money in production, not a financial
| system per se, but it moved amounts around external systems
| that often would include some financial ones. It worked
| surprisingly well given the amounts involved (anywhere from
| tens to thousands of EUR/USD), and when I asked about the off
| by +-0.01 errors every now I was told they were "not worth
| fighting by the customers".
| u320 wrote:
| Float can be justified where performance is more important
| than accuracy. Which does happen sometimes in the financial
| world.
| kawhah wrote:
| no, integers are generally used. BCD is fixed-point in any case
| so it's just an inefficient integer representation.
| iamds wrote:
| why add the complexity of bcd when you can just put in it units
| (e.g. cents) where there's no decimal point?
| 8organicbits wrote:
| What do you do if heavy deflation causes the government to
| release a $0.001 coin? A cent isn't a fundamental unit.
|
| Edit: as another hypothetical, what if the $0.001 coin is
| released to support micropayment use cases?
| pix128 wrote:
| Different currencies already have different rules. Any good
| accounting software isn't going to assume US cents. Update
| your currency table to include a version of USD in
| increments of $0.001. Update the amounts on a need-be
| basis. ( Multiply by 10 and change the currency type)
| dahfizz wrote:
| These systems use something like 10^-8 as the implied
| decimal in the real world. Some forex exchanges even go to
| 10^-9
| out_of_protocol wrote:
| Fiat currency can go to -4 i think, crypto currency going
| to -18. And that's whole units like cents P.S. crypto
| things are using uint256 internally, and this type don't
| exist in most languages. Using int64 can work out,
| sometimes, and will usually break soon enough
| circuit10 wrote:
| In a situation like that I think it would be better to have
| the system not work until it's fixed than to potentially
| lose precision and work with untested inputs
| DamonHD wrote:
| Actually that would break so many things (the cent as the
| smallest unit in law and in custom where that is currently
| the case) that governments may by preference issue a whole
| new currency instead of stir that pot.
| eesmith wrote:
| I thought the smallest unit in the US was the mill.
| https://en.wikipedia.org/wiki/Mill_(currency)
|
| > https://www.law.cornell.edu/uscode/text/31/5101 says
| "United States money is expressed in dollars, dimes or
| tenths, cents or hundreths,[1] and mills or thousandths.
| A dime is a tenth of a dollar, a cent is a hundredth of a
| dollar, and a mill is a thousandth of a dollar."
|
| > [1] So in original. Probably should be "hundredths,".
|
| About the only time you see values given in mills is with
| gas prices, like $4.999/gal, though often denoted as
| tenths of a cent. It's also indirectly used in property
| taxes.
| kemotep wrote:
| This year on our local ballot there is a tax levy to
| approve an increase to the property tax by 5 mills per
| 100,000 dollars of assessed property value. Allegedly
| allowing them to raise a few million over the next 10
| years to pay off an addition to the school.
| jl6 wrote:
| Worth noting that hyperdeflation has never happened, which
| is kind of interesting because it theoretically could.
| throwaway10965 wrote:
| Not sure what exactly you call hyperdeflation, but
| something like that has occurred in communist
| Czechoslovakia in 1953.
|
| https://cs.wikipedia.org/wiki/%C4%8Ceskoslovensk%C3%A1_m%
| C4%...
| kybernetikos wrote:
| I believe that economists generally think that a small
| amount of inflation is good for the economy, and that
| deflation is bad (because it leads to reductions in
| spending and investment, potentially causing a vicious
| circle). It's also relatively easy to counteract - just
| print more. In order for hyperdeflation to occur you'd
| need a currency where the issuing body didn't believe
| deflation was bad, or didn't care.
| kemotep wrote:
| Bitcoin has a hyper deflationary monetary policy hard
| coded in.
| [deleted]
| Sohcahtoa82 wrote:
| Yup, and as a result, nobody wants to actually treat it
| as the digital currency that it was originally set out to
| be.
|
| Anybody who truly thinks Bitcoin could hit $100K value
| certainly doesn't want to spend them.
| u320 wrote:
| It's not really symmetric. It's not hard to imagine a
| situation where everyone stops believing something (a
| currency) is not worth anything anymore. But why would
| somebody believe that _nothing_ except currency is not
| worth anything?
| GTP wrote:
| I think you could easily convert every stored value to the
| new unit of measure by multiplying by an appropriate
| factor. In your example that would mean multiplying all the
| old values by 10. But when you're designing such software,
| you could also be conservative and use a smaller unit than
| cents (which probably many financial sw already do, as you
| already have things considering fractions of cents like
| gasoline prices).
| atemerev wrote:
| Division. 1/x is a common operation in finance (particularly
| in trading), and you'll get all sorts of trouble if you try
| to express everything in cents.
|
| So, you'll need subpenny fractions (e.g. 8 decimal points),
| or BigDecimal, or decimal-normalized floats.
| yyyk wrote:
| Decimal float has a larger range and a more natural
| representation when debugging than fixed point. Either way
| works well though.
| manicennui wrote:
| Because it is very common to need to deal with fractions of a
| cent in intermediate calculations.
| bowsamic wrote:
| I've never seen anyone use floating point for money in their
| bespoke applications
| bradley13 wrote:
| QuickBooks almost certainly used float in the early versions
| of their currency conversion. We saw lots of accumulated
| rounding errors that really couldn't be explained any other
| way.
|
| That was maybe 15 years ago - hopefully they've fired that
| programmer and fixed it in the meantime. We don't know,
| because we don't use QuickBooks any more.
| MrBuddyCasino wrote:
| Count yourself lucky.
| DamonHD wrote:
| Every banking client did use double for the actual
| calculation phase of their derivatives trades.
|
| (And some of our back-end systems then did ludicrous broken
| wrong-headed rounding to turn them into fictional currency
| values... Ho hum.)
| atemerev wrote:
| You _can_ use floating point if you are very careful and know
| what you are doing and know about decimal normalization (see
| e.g. OpenHFT implementation for high-frequency trading:
| https://github.com/OpenHFT/Chronicle-
| Core/blob/ea/src/main/j...)
|
| But if you are not an expert, you better stick to BigDecimal
| and absorb the performance costs.
| rvnx wrote:
| Nice share! Interesting sorcery in their code:
|
| > final double residual = df - ldf + Math.ulp(d) * (factor
| * 0.983);
| __s wrote:
| I worked on some software in the past where I converted
| double to C#'s decimal type. Unfortunately it wasn't so easy
| on the shop's old php stuff, but there I was more concerned
| with fixing their SQL injection issues rather than their
| rounding errors
| zorked wrote:
| Nubank used floating point - not in their real backend
| systems, but somewhere in their app. It was a bit amusing
| when people on Twitter found out certain very specific,
| arbitrary-looking amounts were not able to be transferred,
| then the computer scientists noticed what they had in common.
| atharv37 wrote:
| 'hi"
| MagicMoonlight wrote:
| Intel should release a new premium CPU with AccountMax Cores
| (just add a few registers for 256 bit math)
|
| Of all the problems to solve, the size of the registers is the
| most trivial.
| walnutclosefarm wrote:
| I'd like a report back from TigerBeetle on how many applications
| they actually support where the high order 64 bits are nonzero. I
| would note that the entire US GDP is less than 10^15 cents, and
| that 2^64 accommodates just shy of 10^19 in signed integers. So,
| even if your database had a justification for thousands of a cent
| transactions (not intermediate results, but recordable
| transactions), you'd still need to have transaction entries
| larger than the US annual GDP to roll over into the high order 64
| bits.
|
| TigerBeetle may have made the right choice for some market, but I
| predict that there are vanishingly few sales calls where this
| becomes an important selling point, unless it's potential
| customers wondering why they are wasting all those bits and
| checks for a whole lot of freakin' zeros.
| jorangreef wrote:
| To be fair, I used to think like this too, but chatting with
| multiple large exchanges/brokerages made us realize this was a
| thing.
|
| > less than 10^15 cents
|
| There are systems that don't work in terms of cents (cf. the
| examples of issues in many of the comments here), or even in
| thousandths of a cent, but with significantly more precision.
|
| Literally, in other words:
|
| Where you run into problems then, with 10 ^ n integer scaling,
| is when n is large. When n is large, you aren't left with
| sufficient room in the remaining bytes to represent the whole-
| number part. In trading systems, for instance, you can easily
| hit 10 ^ 10 to represent fractional traded prices.
|
| Concretely, if you need to scale by 10 ^ 10, then your whole-
| number part is 2 ^ 64 / 10 ^ 10 = 1,844,674,407, which isn't
| terribly large.
| walnutclosefarm wrote:
| I'm not sure I understand what you're saying. Are you saying
| that these exchanges are trading at prices to a precision of
| 10 ^ -10 dollars (or other currency)? I saw private exchanges
| pricing to hundredths of a cent (a long time ago - it's been
| a decade and half since I worked on Wall Street or in the
| City) or yen, but never any finer than that. Even then, all
| transactions were recorded in whole cents.
|
| I'm sure you've done your homework, and I'm long out of the
| finance business, but even so, I think the applications where
| this matters are, as financial applications go, very unusual.
| hot_gril wrote:
| Why do exchanges use such high precision for fractions?
| jorangreef wrote:
| To represent prices that are traded fractionally.
| hot_gril wrote:
| But nothing can do that exactly, for example 1/3 has an
| infinitely long decimal or binary representation. So why
| round to 10^-10 as opposed to something like 10^-3?
| jorangreef wrote:
| For sure. We didn't pick 10^10 scaling. It's just what
| some massive brokerages/exchanges actually use. The fact
| that these were not necessarily crypto made us take note.
|
| At the same time, you can understand that 10^10 scaling
| is at least significantly more precise. And I can imagine
| these things are viral too, who you trade with, also
| determines your minimum resolution. You can always
| downsample in presentation, but once downsampled in
| storage, it's impossible to upsample.
|
| It also wasn't the only use case. But it tipped the
| scales.
| hot_gril wrote:
| Yeah, was just curious if the brokerages explained their
| reasoning in detail. Even if it's just viral, someone big
| had to have a reason to start the trend.
| jorangreef wrote:
| Hey! Thanks for your curiosity. This was news to us too.
| And I think we spent about a year thinking about this
| before we swapped for a bigger piggy! :)
| returningfory2 wrote:
| There's one small part of the article that IMO is sort of key
| to understanding the why:
|
| > [for every account] we keep two separate strictly positive
| integer amounts: one for debits and another for credits
|
| It is not sufficient that their integer type is able to handle
| individual transactions. Their integer type must be able to
| handle the sum of the absolute value of all transactions that
| have occurred on an account. And I think it's easy to come up
| with realistic situations where you hit that.
|
| So say you take the NYSE, which trades about ~$18 billion per
| day [0]. This is ~$1.8 trillion cents, or about 2^51
| microcents. After 2^12 business days (~=16 years) you'll
| already be hitting the limit. (This is just a toy example ofc.)
|
| [0] https://www.nyse.com/trading-
| data#:~:text=The%20New%20York%2....
| bsder wrote:
| The only good thing that Bitcoin ever did was create a real world
| use case that breaks shitty software handling financial numbers.
|
| Either the programmers have to do the right thing or tell their
| boss that they can never support Bitcoin.
|
| Both options give me a warm, fuzzy feeling inside when I watch
| them in real time.
| sambeau wrote:
| I once worked on a banking terminal for a large bank. My first
| attempt was sent back as there wasn't 'enough zeros on the buy
| button'. It could do PS999,999,999
| undersuit wrote:
| Man, reminds me of my first work project, we rebuilt the time
| clock in 2006 for our department. I knew about inaccuracies in
| floating math so I thought I was taking precautions, but in the
| end my first native PHP float implementation introduced enough
| drift in just the hours field that we'd lose $40 a year. Rebuilt
| for the Decimal object and it lasted long enough until the entire
| organization bought it's own COTS solution.
|
| Now I'm trying to remember if I watched Office Space before or
| after...
___________________________________________________________________
(page generated 2023-09-19 23:02 UTC)