Tuesday, April 18, 2017

Inexact results and monetary calculations...

Inexact results and monetary calculations...  There are a few things worth pondering about making calculations with money where the results are not exact quantities.

Consider the case of inexact results that are expected to be inexact.  A common example of this is a compound interest calculation that involves logarithms, powers, and roots – not much chance of an exact answer on those!  In cases like this, what we need for money is for the answer to be rounded to the nearest conventional unit of money (for instance, the nearest penny in USD).  This is, however, a bit more complicated than you might think.

Consider a case in USD, where we want to round to the nearest penny.  Suppose our unrounded result was 0.121 – that's easy, the rounded result is 0.12, rounded down (toward zero).  Similarly, 0.346 would rounded up to 0.35.  Both of those are obvious and uncontroversial.  But suppose our unrounded result was 0.115?  Do we round that down to 0.11, or up to 0.12?  In both cases, the difference between the rounded and unrounded values is the same: 0.05.  How do we choose between rounding up or rounding down?

Most of us old enough to predate the “new math” were taught in elementary school to round such values up, all the time.  I have no idea what the hell kids are taught these days, except I'm confident it's not very useful.  However, always rounding halfway values up over a large number of results introduces a bias toward larger average results.  Bankers and their customers noticed this a long, long time ago.  Some clever accountants came up with a simple solution that's easy to implement and removes the bias: “half even” rounding.  In this kind of rounding, a result like 0.115 is rounded so that the next most significant digit is rounded to an even value – so round up to 0.12 in this example, because 2 is even and 3 is not.  If the unrounded result was 0.165, though, then we'd round down to 0.16, because 6 is even.  I should note that one could also use a “half odd” rounding to accomplish the same thing.

In some kinds of financial calculations, though, even this solution isn't what's needed.  For instance, in certain kinds of models you always want to round toward zero.  There are a half-dozen or so different kinds of rounding that are occasionally useful in monetary calculations.  The way monetary quantities are represented really needs to support all of these rounding flavors.

Now lets consider a different case: where results are expected to be exact, and an inexact result indicates a mistake of some kind.  I ran into a case like this in a stock trading application, where we multiplied the number of shares bought or sold times the sales price to get a “lot price”.  Since shares of stock are indivisible (e.g., you can't buy 1.5 shares of IBM), that result should always be exact, to the penny.  If it's inexact, then something is wrong – perhaps someone mistakenly entered a fractional share quantity, or there's a bug in the program.  For these sorts of situations, it is very useful to know whether a monetary quantity is exact or inexact (e.g., has been rounded).  The way monetary quantities are represented should support this.

Finally, sometimes in monetary calculations we really don't want inexact values to be rounded.  For example, suppose we had 10,000 USD that we want to divide in thirds and distribute to three accounts.  The rounded, inexact result of that would be 3,333.33 USD that we put into each account – but that only adds up to 9,999.99 USD – we “lost” a penny and now our books are out of whack.  The way financial applications generally solve problems of this type is to use some algorithm to choose a lucky account, and they give that account the extra penny (in this case).  These algorithms themselves are interesting, as they need to be repeatable (so you can't just roll the dice) for audits, but they are not the problem I'm discussing here.  It's knowing that we have an inexact result, and how much is “left over” to distribute that I care about today.

This sort of problem always has a division operation at the root of it.  The general solution is really simple: you need a division operation that gives you the floor of the quotient, and the remainder.  So the result of the division in the example above would be 3,333.33 with a remainder of 0.01.  The way monetary quantities are represented must include the division-with-remainder operation.  Ideally it would allow returning quotients that are floor, ceiling, nearest toward zero, or nearest away from zero (all with appropriately adjusted remainders) because all of these are useful in some financial applications.

No comments:

Post a Comment