5 ms·
Di you try it? Have you written financial software? This is terrible advice. Even the most naïve calculation, such as computing total amount paid at 8% compoun
by SideQuark 4y ago
Di you try it? Have you written financial software? This is terrible advice.
Even the most naïve calculation, such as computing total amount paid at 8% compounded monthly over a 30 year mortgage, ends up wrong by over $100,000 compared to the correct answer. This is a pretty common mortgage calculation.
Here's the expression to evaluate: 1000000 * (1 + (8/100)/12) ^ (12*30). Do it, rounding to d digits of accuracy at each basic expression, and here are the errors you get:
2 -> 25 million
3 -> 1.3 million
4 -> $131,170
5 -> $13,040
6 -> $1304
7 -> $130
8 -> $13
9 -> $1.3
10 -> $0.13
11 -> $0.013
....
Thus, using anything less than a double, over large portfolios, is a terrible, terrible idea, even for such a simple calculation.
Anything actually useful, such as summing such calculations over some portfolio, or handling sum over variable interest rate calculations, or, well, pretty much anything, completely pukes at 4 decimals.
This is why people that don't develop floating point with a solid understanding of how to compute and check things like condition numbers for calculations should not give advice on how much precision to use for things.
In fact, I'm hard pressed to find any reasonable financial computation that is not crap at 4 decimals.
This is perhaps why your "guess .. that at least half of the cases where floats are applied could be better served using scaled integers" is not a very good guess.
The proper answer is do not pick either unless one really understands the numerics, so if someone chooses "scaled numerics" over floating point because they find floating point complicated, then they are most certainly made an uninformed choice and likely an error.
Choosing floating point calculations over scaled numerics is much less likely to bite someone doing numerical math, since it can scale properly and dynamically to help hide their ignorance of numerical issues.
- jqpabc123 4y agoYou'll probably want to use 64 bit integers here just in case you need to deal with the national budget. Assume Principal (P) is provided in pennies. In pseudo code: P := P * 100 //temporarily scale out 2 extra digits for accuracy (4 decimals total) for I:=1 to 360 do P := P + ((P * 8)/1200) return (P+50) div 100 //round back to nearest penny By my calculations, this returns 1093572966 pennies or $10,935,729.66 How did I do? Thanks for playing.
- SideQuark 4y agoCongratulations - you're 0.3 cents off, despite careful ad-hoc tuning you did to solve only the one set of numbers you set out to. Too bad your method still fails for a whole range of valid mortgages :) Like what happens when you use your algorithm for a 10M mortgage? Oops! Just add some more scaling, ad hoc fixes.... Then $100M? Oops! More scaling and fixes. And so on. Enough ad-hoc fixes and you'll re-invent float-point, but badly. This is why such ad hoc goofiness is a bad idea. Despite you trying real hard to make a good algorithm, you still failed. Try using modern high decimal fractional mortgage rates. Oops. Try using a longer term, like long term rentals of commercial land for 100+ years. Oops again! Yet my one line floating point code handles them all, no fiddling, no errors, no chasing down bugs every time someone puts other numbers into the code. Are you going to hand fiddle everytime? Try other rates, some times rates are many more digits than you assume - are you now going to hand analyze each single problem and hand code a single problem solver? Floating point does them all. Of course, you will eventually stumble onto more and more precision, then you will fail to handle large numbers. Eventually you might try using two 64 bit integers, more or less trying to accomodate what a double simply does out of the box. And then you will have reinvented floating point numbers, just much slower and more error prone. You're replacing floating point which just works, by having to be super careful of order of operations, thereby making it more likely a programmer without knowing the nuances of numerics will fail. Prime example: you decided to replace a rate, converted to percent with a division, then to a per-time step with another a division, by a multiplication. Why? because if you didn't you puke as I demonstrated. You also needed to do some prescaling, leading to bugs. Not all prices are in pennies. Then you needed to "assume" principal was in pennies. Why? to make your ad-hoc method work. Mine worked in dollars, yen, lira, pesos... all sorts of scales, and yours would need tweaking and hackery to handle all the scaling you will need for wide ranging currencies (or dollar amounts) - each leading to bugs. >Thanks for playing. You're welcome. If you really want to play, let's each put forth a single code snippet, and see if the other one can propose a simple mortgage representative of one in the real world that breaks the other's code. Care to play? So write your best method to calculate mortgages, across any type of simple mortgage I will pick (principal P (in an arbitrary currency), annual rate r (expressed as percent), compounding rate t per annum, term in years n), and I will submit my floating point code against yours, and I will demonstrate yet again why yours fails. My code: total = principal * (1+((rate/100)/t)) ^ (n*t) No many places to make a mistake there. And your code? So far your method seems more ad-hoc and error prone than pretty much anything any programmer simply copying a formula out of a book would end up with. This is exactly why your advice is bad. It will lead to people making mistakes :) >Thanks for playing. You're welcome. It has been enlightening. I look forward to your next algorithm.
- gilbetron 4y agoIn fact, you want to use something like Java's BigDecimal for financial calculations: https://dzone.com/articles/never-use-float-and-double-for-monetary-calculatio https://dzone.com/articles/never-use-float-and-double-for-mo...
- jqpabc123 4y agoYes, that works --- but you can pay a significant price in terms of efficiency and storage headaches. It all depends on your needs. 64 bit integers fit natively within modern processor registers (read max. possible speed) and are still reasonably efficient even when implemented in 32 bit processors. My simple suggestions to avoid loss of of significance, comparison decoherence, "mystery penny" problems and storage convenience are these. - Use 64 bit integers for monetary amounts expressed in pennies. Format as desired for display/printing. - Use 32 bit integers for annual interest rates with amounts scaled to 3 decimals (x1000). For example, 8.000% would be stored as 8000. 8.259% would be 8259. If you think you need more decimals (personally, I doubt it), go for it --- just be sure your math is scaled appropriately. - Round and store amounts paid/due to the nearest penny using "banker's rounding". This in itself can cause some minor loss of accuracy (piecewise rounding) which (if any) should be reflected in the "final" payment. - Temporarily use 4 additional decimals for any multiplication or division intensive calculation. Round and return a final resultant to the nearest penny. - This generally works just fine for routine calculations involving amounts below $100 billion or so which is probably 99.9% of financial apps. Simple totals can go up to $ trillion range. "BigDecimal" (which is really infinite range integer math with library routines available in many different languages) might be a candidate for the remaining 0.1% but personally; all things considered, I would investigate 96 or 128 bit integer math first if more range is needed. C/C++ and Rust have an int128 type. Your mileage may vary.
- SideQuark 4y ago>but you can pay a significant price in terms of efficiency and storage headaches Yet the code you posted above as using int64 does not in fact work using int64, it requires arbitrary sized integers as I demonstrated above. Did you even check your code? Your example above has the (P*R) term overflowing leading to nonsense results. Man this is funny - you somehow thought you were using int64 in your calcs but you were not :)
- hnews_account_1 4y agoI don’t think anyone means to put ALL calculations through a reduced representation. That’s a terrible idea. But if you are discounting cash flows or something, it won’t make that much of a difference if you leave the discounted version in full float / double representation and then add them or reduce them to 2 decimals before adding* High finance uses float / double in general and doesn’t bother with the nuances of decimal representation or IEEE 754 unless they’re working too close to the silicon rather than doing model work in higher abstractions. * software that allows only 2 decimal representation must account for these discrepancies by default even if it’s only off by a few cents