6 ms·
>0.3 cents is quite a bit different than your earlier claim --- "completely pukes at 4 decimals". Yep - plug 100M into your just posted code. Was it correct? N
by SideQuark 4y ago
>0.3 cents is quite a bit different than your earlier claim --- "completely pukes at 4 decimals".
Yep - plug 100M into your just posted code. Was it correct? Nope?
>So within acceptable legal tolerance.
Yes, when you hand craft to solve one specific instance by carefully tuning. I noticed you ignored posting code you claim will handle mortgages in general.
Care to cite a law you think gives "legal tolerance"? I suspect you're making that up. You must mean 'within my understanding that being within a cent on a single transaction is ok" which is simply not true.
Not when you process thousands of loans (I develop the algorithm used to price tranches for mortgage bundling for a large mortgage company when I was in grad school - I do know a bit about this space, and I certainly know a lot about numerics - floating-point, fixed point, adaptive, unums, the whole lot - you're simply compounding your errors).
>My standard, generalized, library routine is equally brief and works for amounts up to $100 billion with any interest rate expressed out to 3 decimals --- with nary a float in sight.
Post it :) Even tell me what numbers you think it handles. I bet I still break it, and my naive floating-point one above handles it.
I don't think you understand floating-point. Do you ever check condition numbers on your code? Do you know what condition numbers are? I'll take you inability to post this simple magic algorithm you claim you have as evidence you don't have it.
For anyone following this thread, this example pretty clearly shows why naive replacement is going to bite you.
- jqpabc123 4y agoThe generalized routine below provides compound interest Future Value using scaled integer math (no floats) to 14-15 digits of accuracy --- roughly comparable to a double float while avoiding comparison decoherence. It aims for results accurate to the penny while a negative result indicates an overflow failure. In comparison, floating point math provides no warning when the accuracy of the mantissa is exceeded --- out of sight, out of mind --- by design. scaleFV(P,R,C,Y) int64 SP := 10000 //temporary principal scale factor, 4 decimals if (P>SP*1000) SP *= 10 //extend accuracy for larger amounts SR := 1000 //annual rate scale factor, 3 decimals (pre- applied to R) N := C * Y //total number of compounding periods D := C * 100 * SR //period rate divisor P := P * SP //scale the principal (int64) while N>0 do P := P + ((P * R) div D) //compound principal with period interest decr N //count the period return (P + SP div 2) div SP //unscale result, round back to nearest penny Example: P = 10000000000 $100 million in pennies R = 8000 8 percent scaled to 3 decimals C = 12 12 compounding periods per year Y = 30 30 years Result = scaleFV(P,R,C,Y) = 109357296578 pennies or $1,093,572,965.78
- SideQuark 4y ago1) I posted my code as ` total = principal * (1+((rate/100)/t)) ^ (n*t)`, and you claimed your 10 line "My standard, generalized, library routine is equally brief". By "equally brief" did you mean an order of magnitude larger? 2) Your code and example does not work using 64 bit integers. Using only 64 bit integer math, your code gives 11605682736, off by 90% (easily checked in C/C++/C#). Your math overflows, so you're not using scaled integers; in order to work, your code requires arbitrary sized integers for the loop. Did you not realize this? So you're not using scaled integers as int64s. You're using unbounded sized integers. Your (P*R) term repeatedly overflows a 64 bit int when calculating your example. 3) If you're going to use arbitrary sized integers, then simply compute the exact numerator and denominator, then divide. It's actually accurate, as opposed to your mess. And it's simple to code. 4) You claim "a negative result indicates an overflow failure", which is wrong, since it can overflow twice (or more) in the same calculation, and, since you're using arbitrary sized integers internally, the conversion depends on non-portable behavior. Both of these can be demonstrated quite easily. 5) You claim "floating point math provides no warning when the accuracy of the mantissa is exceeded," which is wrong - it marks it with an Infinty using IEEE 754 math, required by a significant amount of languages, and provided on all major pieces of hardware), which will never revert as your error code can. And for someone understanding numerics (and condition numbers), the calculation is easy to extend with the accuracy of the result so the used will know error bounds. 6) Your code is amazingly slow: your int64 version (which fails almost all tests) is ~6000x slower than the pure double version, and the arbitrary sized int one is 45,000x slower (C#, Release build, tests run over the examples below). 7) Examples where your algorithm fails. Inputs are numbers that occur in real mortgages: interest 18.45% happened in the 1980s, 50, 75, 100 year terms exist (50 is getting common in CA), 24 payments represents bi-weekly payoffs (and some places compound daily, or 365 times a year [1]). To test accuracy of even your int64 routine, lower principal amounts are below to show both your routines (the honest int64 and the arbitratry integer one) still fail. "My routines" are the double one above and, since you require arbitrary sized integers, I'll test one that simply computes exact numerator and denominator then divides: 10000,18450,365,50 -> both your int64 and arbitrary precision are off by $10.08, my routines are both perfect. Want a lower interest rate? 10000,8000,365,50 -> both of yours are off by $0.12, both mine are still perfect. Let's push them with a longer term, up the principal: 100000,8000,365,100 -> both yours are off by $6.72, both mine are perfect Now, since your int64 version pukes immediately on larger numbers, let's only look at the arbitrary sized versions. 500000,8000,365,100 -> yours off by $0.68, mine perfect Maybe the problem is the daily compounding? 100000000,18450,12,50 -> yours off by $0.03, mine perfect 100000000,18450,12,100 -> yours off by $0.34, mine perfect And for fun, let's look at a $100k loan, 15%, compounded hourly (say 8760 times a year) like a bad credit loan, for 25 years.... (Note your routine is stupidly slow for this one): 100000,15000,8760,25 - both yours are off by $1.21, both mine are correct. I can keep producing errors all over this frontier. 8) So, to avoid "comparison decoherence" (!?) because you don't understand floating point (which can be made bit exact, as I've done on many projects for binary file format interop), you instead produce demonstrably buggy, numerically faulty, slow, memory unbounded code? This is why people should not take advice on numerics from someone that does not understand numerics. [1] https://www.rocketmortgage.com/learn/compound-interest https://www.rocketmortgage.com/learn/compound-interest