Currency representation in Lua

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Currency representation in Lua

Diogo Mildenberger
Hello!

Has someone any experience to share about implementing a system that deals with currency values? I have already been bitten by the problems described in http://floating-point-gui.de/ and I want to find a better way.

It is mentioned in that guide and elsewhere about using fixed-point arithmetic (https://en.wikipedia.org/wiki/Fixed-point_arithmetic even mentions GnuCash took the same route), and from what I read, it is implemented using scaled integers, pretty much. Is that it? Has anyone some insights? 

Thank you!

PS.: Some side tips in this list do stand out for me, like the http://floating-point-gui.de/ previously mentioned. Thanks!
Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Doug Currie
On Sun, Sep 4, 2016 at 8:20 PM, Diogo Mildenberger <[hidden email]> wrote:
 
Has someone any experience to share about implementing a system that deals with currency values? I have already been bitten by the problems described in http://floating-point-gui.de/ and I want to find a better way.

The two common approaches are fixed point, as you mentioned, and General Decimal Arithmetic, which is basically base-10 floating point. See: http://speleotrove.com/decimal/

Ten years ago I made a Lua binding for IBM's General Decimal Arithmetic library decNumber called ldecNumber


It does what you need, but is stuck at Lua 5.1. It depends on some Lua 5.1 features that were removed in 5.2, and would be a bit of work to redo. There have also been some updates to decNumber that ought to be incorporated if ldecNumber is updated. If you work on the library you might consider using decQuad (decimal128) if you can get by with 34 digits of precision; the present version of ldecNumber uses arbitrary precision decNumber set to 69 digits of precision.

e

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Luiz Henrique de Figueiredo
In reply to this post by Diogo Mildenberger
> Has someone any experience to share about implementing a system that deals
> with currency values?

Express your amount in cents, not dollars (or euros or reais).
You can then use integers instead of floats.
It works even in Lua versions before 5.3

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Sean Conner
It was thus said that the Great Luiz Henrique de Figueiredo once stated:
> > Has someone any experience to share about implementing a system that deals
> > with currency values?
>
> Express your amount in cents, not dollars (or euros or reais).
> You can then use integers instead of floats.
> It works even in Lua versions before 5.3

  Just a quick question---is there a smaller unit than the Euro?  Or Reais?
While I can't complain about using cents over dollars [1], I think there
might be some issue with currency conversion.

  -spc

[1] As a citizen of the United States

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Coda Highland
On Sun, Sep 4, 2016 at 8:24 PM, Sean Conner <[hidden email]> wrote:

> It was thus said that the Great Luiz Henrique de Figueiredo once stated:
>> > Has someone any experience to share about implementing a system that deals
>> > with currency values?
>>
>> Express your amount in cents, not dollars (or euros or reais).
>> You can then use integers instead of floats.
>> It works even in Lua versions before 5.3
>
>   Just a quick question---is there a smaller unit than the Euro?  Or Reais?
> While I can't complain about using cents over dollars [1], I think there
> might be some issue with currency conversion.
>
>   -spc
>
> [1]     As a citizen of the United States
>

A one-hundredth division of a euro is also called a cent.

The real is divided into 100 centavos, which is a straightforward translation.

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

KHMan
In reply to this post by Sean Conner
On 9/5/2016 11:24 AM, Sean Conner wrote:

> It was thus said that the Great Luiz Henrique de Figueiredo once stated:
>>> Has someone any experience to share about implementing a system that deals
>>> with currency values?
>>
>> Express your amount in cents, not dollars (or euros or reais).
>> You can then use integers instead of floats.
>> It works even in Lua versions before 5.3
>
>    Just a quick question---is there a smaller unit than the Euro?  Or Reais?
> While I can't complain about using cents over dollars [1], I think there
> might be some issue with currency conversion.

Some systems do need more precision than cents. Here is an example
from Newark/Element14 for a rather expensive SMD chip resistor (USD):
1+ $0.083
50+ $0.016
100+ $0.012
Switching currencies, here is another item in RM (Ringgit Malaysia):
1+ RM0.56 (RM0.5936)
10+ RM0.09 (RM0.0954)
100+ RM0.05 (RM0.053)

The number formatting does not look ideal, but it sure looks like
the values are exact. There are items on sale for $0.001, mostly
SMD chip resistors, I haven't seen a smaller price. I buy 100, the
total price becomes $0.10. But, uh, the shopping cart popup
reports $0.00 for unit price, someone messed up there.

I'm sure their Finance people and IT people are on top of this
thing... Whatever their database is using, it appears to be
dealing in exact values. But it does illustrate the complexities
of a website for global online sales where individual items can be
pretty cheap, pricing can be smaller than 1 cent, etc.

--
Cheers,
Kein-Hong Man (esq.)
Kuala Lumpur, Malaysia


Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Rob Kendrick-2
In reply to this post by Diogo Mildenberger
On Sun, Sep 04, 2016 at 09:20:13PM -0300, Diogo Mildenberger wrote:

> Hello!
>
> Has someone any experience to share about implementing a system that deals
> with currency values? I have already been bitten by the problems described
> in http://floating-point-gui.de/ and I want to find a better way.
>
> It is mentioned in that guide and elsewhere about using fixed-point
> arithmetic (https://en.wikipedia.org/wiki/Fixed-point_arithmetic even
> mentions GnuCash took the same route), and from what I read, it is
> implemented using scaled integers, pretty much. Is that it? Has anyone some
> insights?

Another thing that is important to remember: Not all currencies are
decimal, and actually most currencies are /centimal/.

There exist currencies where the subdivision is not 100: 10 and 1000
exist.  Then there are currencies with no subdivision at all, such as
Yen.

When handling money calculations, you basically have to go and read the
Wikipedia article for every currency you're ever likely to handle so you
can manage all the hideous corner cases.

B.

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Scott Morgan
On 05/09/16 09:39, Rob Kendrick wrote:
> When handling money calculations, you basically have to go and read the
> Wikipedia article for every currency you're ever likely to handle so you
> can manage all the hideous corner cases.

It gets worse than that. You have to be careful of the order you perform
certain operations on the items you're pricing. Things like; do you
apply VAT/sales tax on the total of an order, or on each item.

These details will be part of the tax codes or the various regions
you're dealing with. I think they'd also mention the precision of the
calculations needed (e.g. calculate to 1/10th of a cent)

Scott


Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Matthias Kluwe
In reply to this post by Diogo Mildenberger

Hi!

Am 05.09.2016 03:40 schrieb "Diogo Mildenberger" <[hidden email]>:

> Has someone any experience to share about implementing a system that deals with currency values? I have already been bitten by the problems described in http://floating-point-gui.de/ and I want to find a better way.

Before jumping to conclusions, I'd like to know what problem you actually encountered (besides from "my numbers don't add up").

Regards,
Matthias

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Doug Gale
In reply to this post by Diogo Mildenberger
Double precision floating point can represent all integers up to +-2^53 exactly. You should represent your amounts as the smallest unit of currency, such as cents. Also be sure to round results to the nearest integer after all multiplications and divisions. Additions and subtraction of integer values will be exact.


Sent from my Samsung device over Bell's LTE network.


-------- Original message --------
From: Matthias Kluwe <[hidden email]>
Date: 09-05-2016 9:34 AM (GMT-05:00)
To: Lua mailing list <[hidden email]>
Subject: Re: Currency representation in Lua

Hi!

Am 05.09.2016 03:40 schrieb "Diogo Mildenberger" <[hidden email]>:

> Has someone any experience to share about implementing a system that deals with currency values? I have already been bitten by the problems described in http://floating-point-gui.de/ and I want to find a better way.

Before jumping to conclusions, I'd like to know what proble you actually encountered (besides from "my numbers don't add up").

Regards,
Matthias

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Coda Highland
On Mon, Sep 5, 2016 at 2:07 PM, Doug <[hidden email]> wrote:
> Double precision floating point can represent all integers up to +-2^53
> exactly. You should represent your amounts as the smallest unit of currency,
> such as cents. Also be sure to round results to the nearest integer after
> all multiplications and divisions. Additions and subtraction of integer
> values will be exact.

Nitpick: The smallest unit of currency may not actually be a unit of
legal tender; as discussed elsewhere in the thread, the smallest unit
might be for example tenths of a cent.

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Roberto Ierusalimschy
> On Mon, Sep 5, 2016 at 2:07 PM, Doug <[hidden email]> wrote:
> > Double precision floating point can represent all integers up to +-2^53
> > exactly. You should represent your amounts as the smallest unit of currency,
> > such as cents. Also be sure to round results to the nearest integer after
> > all multiplications and divisions. Additions and subtraction of integer
> > values will be exact.
>
> Nitpick: The smallest unit of currency may not actually be a unit of
> legal tender; as discussed elsewhere in the thread, the smallest unit
> might be for example tenths of a cent.

If you use Lua integers and thousandths of cents as your unit, you will
be able to represent up to ~90 trillion USD. That seems enough for most
uses.

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Paul E. Merrell, J.D.
Tangentially related: There is code for unit conversions on the wiki.
[1] I tested it with Lua v. 5.2; haven't tested with 5.3.

Best regards,

Paul

[1]. <http://lua-users.org/wiki/UnitConversion>


--
[Notice not included in the above original message:  The U.S. National
Security Agency neither confirms nor denies that it intercepted this
message.]

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Tim Hunter-3
In reply to this post by Doug Gale
Rounding. That’s a tricky topic. Rounding can mean many things, so be sure to study up on it before assuming you know what to do.


On Sep 5, 2016, at 5:07 PM, Doug <[hidden email]> wrote:

Also be sure to round results to the nearest integer after all multiplications and divisions.

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Soni "They/Them" L.


On 05/09/16 08:28 PM, Tim Hunter wrote:

> Rounding. That’s a tricky topic. Rounding can mean many things, so be
> sure to study up on it <https://en.wikipedia.org/wiki/Rounding> before
> assuming you know what to do.
>
>
>> On Sep 5, 2016, at 5:07 PM, Doug <[hidden email]
>> <mailto:[hidden email]>> wrote:
>>
>> Also be sure to round results to the nearest integer after all
>> multiplications and divisions.
>

Oh, don't remind me of that rounding thread where we came up with 30
different code snippets just to round a number. (Anyone has a link to
it? I don't feel like looking it up .-.)

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.


Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Scott Condit
In reply to this post by Diogo Mildenberger
From: Diogo Mildenberger [hidden email]
Has someone any experience to share about implementing a system that deals with currency values? I have already been bitten by the problems described in http://floating-point-gui.de/ and I want to find a better way.


If you are writing financial programs for e.g. mark-to-model present value, risk and so forth, it’s quite typical for these do deal with doubles only [across huge swathes of systems in banks and investment funds].

If you are writing an accounting or taxation program, you’ll also need to cope with specific rounding schemes imposed externally in addition to the advice on fixed point given  here, and should think like an accountant (double entry et al) so that you don’t introduce other forms of gap,  e.g. not doing
new_balance,old_balance=balance/3,2*balance/3

Regards

Scott

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Thijs Schreijer
In reply to this post by Paul E. Merrell, J.D.

On 06 Sep 2016, at 01:15, Paul Merrell <[hidden email]> wrote:

Tangentially related: There is code for unit conversions on the wiki.
[1] I tested it with Lua v. 5.2; haven't tested with 5.3.

Best regards,

Paul

[1]. <http://lua-users.org/wiki/UnitConversion>


--
[Notice not included in the above original message:  The U.S. National
Security Agency neither confirms nor denies that it intercepted this
message.]


Nice! it actual refers to the “pre-decimalisation British pounds” mentioned earlier as an example

Reply | Threaded
Open this post in threaded view
|

Re: Currency representation in Lua

Diogo Mildenberger
In reply to this post by Doug Currie


2016-09-04 22:27 GMT-03:00 Doug Currie <[hidden email]>:
On Sun, Sep 4, 2016 at 8:20 PM, Diogo Mildenberger <[hidden email]> wrote:
 
Has someone any experience to share about implementing a system that deals with currency values? I have already been bitten by the problems described in http://floating-point-gui.de/ and I want to find a better way.

The two common approaches are fixed point, as you mentioned, and General Decimal Arithmetic, which is basically base-10 floating point. See: http://speleotrove.com/decimal/

Ten years ago I made a Lua binding for IBM's General Decimal Arithmetic library decNumber called ldecNumber


It does what you need, but is stuck at Lua 5.1. It depends on some Lua 5.1 features that were removed in 5.2, and would be a bit of work to redo. There have also been some updates to decNumber that ought to be incorporated if ldecNumber is updated. If you work on the library you might consider using decQuad (decimal128) if you can get by with 34 digits of precision; the present version of ldecNumber uses arbitrary precision decNumber set to 69 digits of precision.


Thanks everyone for such fast (and broad!) reply. 
I spent yesterday taking a look at docs from Doug Currie's suggestion, (l)decNumber, and your other suggestions, and learnt a bit more about the problem.

To clarify, yes, as of now, an integer-based solution would suffice, but I wanted to know if there were other options to keep me from implementing yet another poor man's fixed-point library. Glad to know there are options like decNumber, and I also found out about JavaScript libraries [1] that implement something similar to Java's BigDecimal (unsure if easy to port to Lua, but a starting point).

Answering Matthias about context: It is currently a simple pure-Lua 5.1 application (in x86) for stock trading analysis that deals with Brazilian Real, possibly the occasional US Dollar, so not much "cents variety". My major problem is really "Why don't my numbers add up?" and I had a primitive understanding of what was going on, even have a half-baked solution, but want better. While searching the web, I saw several mentions about "just using integers" and "it's bad to use integers, use a robust decimal arithmetic solution", so I wanted to know from you what options did you know or have tried.
As for rounding, so far I am going with "Round half to even" aka "Bankers' Rounding".

Now I am a little concerned about performance, given that whatever the option is, it is going to be at the very core of the calculations, but will get to try options before jumping to action. I guess the one with most performance would be (l)decNumber (as it is {ANSI} C -- as far as I understood, no hardware support for decimal floating-point in x86).

Diogo

PS.: I consider this yet another example of the "Law of Leaky Abstractions" (http://www.joelonsoftware.com/articles/LeakyAbstractions.html), even my numbers are "not in Kansas anymore"... :P