Representing money in software

David Hopwood david.nospam.hopwood@REDACTED
Mon Jan 2 18:10:31 CET 2006

[resend to the list; I accidentally sent it only to the poster]

David Hopwood wrote:
> Erlang Questions wrote:
>>I was afraid about that.
>>Unfortunately, these numbers represent money in my application :o(
> It sounds like your basic problem is that you don't have an unambiguous
> specification of how your application should handle money. This should
> enumerate *all* of the monetary calculations that your app needs to implement,
> and for each one, it should specify:
>  - the range and precision of each input,
>  - the required precision that must be used for intermediate results,
>  - the rounding method, for any calculation that involves rounding.
> It should also specify the precision at which monetary amounts are displayed
> and input at the user interface, and the formats used at interfaces to other
> software and files/databases (including how multiple currencies are handled).
> Producing this specification is a separate activity from implementing it (even
> if both happen to be done by the same person). In many cases, there are strict
> legal requirements on how many decimal places or significant figures, or which
> rounding method *must* be used [*]. So the spec should be signed off by someone
> whose job it is to know what those requirements are (for all relevant countries
> and situations), such as a qualified accountant.
> [The maximum amounts of money that can be involved in a calculation should be
> chosen generously. You never know which countries that may seem stable now will
> suffer from hyperinflation in the lifetime of the application.]
> Given such a spec, you will almost certainly find that floating point
> arithmetic is of no use whatever in implementing it correctly.
> Generally it's necessary to use integer arithmetic, with integers of sufficient
> size to handle the maximum amount of money that may be involved at the required
> precision. Always check for overflow at every intermediate step, and abort the
> transaction (with a comprehensible error report) if overflow occurs. Even if
> multiple currency support is not needed initially, it's a good idea to think
> about what the upgrade path to that would be.
> [*] For example, here are the requirements for conversion between the
>     national currencies that made up the euro:
>       ARTICLE 4; The conversion rates shall be adopted as one euro expressed
>       in terms of each of the national currencies. They shall be adopted with
>       six significant figures. The conversion rates themselves must not be
>       rounded or truncated when making conversions. The conversion rates shall
>       be used for conversions either way between the euro and the national
>       currency units. Inverse rates derived from the conversion rates shall
>       not be used. Monetary amounts to be converted from one national currency
>       unit into another shall first be converted into a monetary amount
>       expressed in the euro unit, which amount may be rounded to not less than
>       three decimal places and shall then be converted into the other national
>       currency unit. No alternative method of calculation may be used, unless
>       it produces the same result.
>       ARTICLE 5; Monetary amounts to be paid or accounted for, when a rounding
>       takes place after a conversion into the euro unit according to article 4,
>       shall be rounded up or down to the nearest cent, Monetary amounts to be
>       paid or accounted for which are converted into a national currency unit
>       shall be rounded up or down to the nearest sub-unit, or in the absence of
>       a sub-unit to the nearest unit or according to national law or practice
>       to a multiple or fraction of the sub-unit or unit of the national currency
>       unit. If the application of the conversion rates gives a result which is
>       exactly half-way, the sum shall be rounded up.
>     To implement this, you could represent euro amounts as integer multiples
>     of 0.001 euro cents, for example. More generally, there is almost always
>     some fixed precision that can be used; variable-precision representations
>     (such as "floating decimal") are usually an overcomplication.

David Hopwood <david.nospam.hopwood@REDACTED>

More information about the erlang-questions mailing list