caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* What library to use for arbitrary precision decimals
@ 2006-02-19 13:43 Joshua Smith
  2006-02-19 15:44 ` [Caml-list] " Brian Hurt
  0 siblings, 1 reply; 9+ messages in thread
From: Joshua Smith @ 2006-02-19 13:43 UTC (permalink / raw)
  To: caml-list

There are a couple of ways to handle money transactions without
rounding errors.

You could use the Nums library, which provides arbitrary precision
calculations and numbers.   But even with arbitrary precision numbers,
you still can have the situation where you get 405.0345 which if this
were USD, you would still have to round if you wanted to pay someone
this amount.  You will still have the arbitrary precision this way,
however.

The best way to handle money (in my experience) is to use integers. 
Then you can define conversion functions but only have to convert it
to decimal for display purposes.  That way, even if you do a million
transactions you won't lose any information.   You can also handle
non-decimal based currencies/instruments/transactions that way[1]

HTH

-jbs

[1] yes,  there are a (thank god shrinking number) of commodities and
stuff like that in the world that don't use decimal prices.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] What library to use for arbitrary precision decimals
  2006-02-19 13:43 What library to use for arbitrary precision decimals Joshua Smith
@ 2006-02-19 15:44 ` Brian Hurt
  2006-02-19 16:38   ` Richard Jones
  2006-02-19 17:21   ` Jeremy Shute
  0 siblings, 2 replies; 9+ messages in thread
From: Brian Hurt @ 2006-02-19 15:44 UTC (permalink / raw)
  To: Joshua Smith; +Cc: caml-list



On Sun, 19 Feb 2006, Joshua Smith wrote:

> There are a couple of ways to handle money transactions without
> rounding errors.
>
> You could use the Nums library, which provides arbitrary precision
> calculations and numbers.   But even with arbitrary precision numbers,
> you still can have the situation where you get 405.0345 which if this
> were USD, you would still have to round if you wanted to pay someone
> this amount.  You will still have the arbitrary precision this way,
> however.
>
> The best way to handle money (in my experience) is to use integers.
> Then you can define conversion functions but only have to convert it
> to decimal for display purposes.  That way, even if you do a million
> transactions you won't lose any information.   You can also handle
> non-decimal based currencies/instruments/transactions that way[1]

I agree with this recommendation.  The basic idea is that you use fixed 
point.  Say you want to be accurate to one thousandth of a cent (0.001 
cents).  You simply do all calculations in terms of millicents.  So the 
integer 1 represents one millicent.  One penny is represented as the 
integer 1,000- one thousand millicents.  The amount $2,345.67 is 
represented by the integer 234,567,000.

If you use the Int64 module as the basis for your computations, you can 
hold values up to $184,467,440,737,095.51 in size.  This is larger than 
the world's GDP, so it should be large enough.  32 bits isn't enough- that 
only allows you to hold values up to $42,949.67.

Brian


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] What library to use for arbitrary precision decimals
  2006-02-19 15:44 ` [Caml-list] " Brian Hurt
@ 2006-02-19 16:38   ` Richard Jones
  2006-02-19 16:53     ` Brian Hurt
  2006-02-19 17:21   ` Jeremy Shute
  1 sibling, 1 reply; 9+ messages in thread
From: Richard Jones @ 2006-02-19 16:38 UTC (permalink / raw)
  To: caml-list


Before we go too far down the currency track (where I agree, using
integers is the way to go), my actual requirement is for a natural
OCaml mapping for the PostgreSQL NUMERIC/DECIMAL type:

http://www.postgresql.org/docs/current/interactive/datatype.html#DATATYPE-NUMERIC-DECIMAL

The database can define types like NUMERIC(6,4) which means 6 decimal
digits in total, 4 of them after the decimal point -- for example,
12.3456

There doesn't seem to me to be a good natural map for this type in the
stdlib.

Rich.

PS. You can find latest progress on PG'OCaml here:

http://merjis.com/tmp/pgocaml-0.3.tar.gz

I've already converted a few of our bigger programs to use this library.

-- 
Richard Jones, CTO Merjis Ltd.
Merjis - web marketing and technology - http://merjis.com
Team Notepad - intranets and extranets for business - http://team-notepad.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] What library to use for arbitrary precision decimals
  2006-02-19 16:38   ` Richard Jones
@ 2006-02-19 16:53     ` Brian Hurt
  2006-02-19 17:00       ` Richard Jones
  0 siblings, 1 reply; 9+ messages in thread
From: Brian Hurt @ 2006-02-19 16:53 UTC (permalink / raw)
  To: Richard Jones; +Cc: caml-list



On Sun, 19 Feb 2006, Richard Jones wrote:

>
> Before we go too far down the currency track (where I agree, using
> integers is the way to go), my actual requirement is for a natural
> OCaml mapping for the PostgreSQL NUMERIC/DECIMAL type:
>
> http://www.postgresql.org/docs/current/interactive/datatype.html#DATATYPE-NUMERIC-DECIMAL
>
> The database can define types like NUMERIC(6,4) which means 6 decimal
> digits in total, 4 of them after the decimal point -- for example,
> 12.3456

Hmm.  There are problems definin that library.  What are the semantics? 
If I add a NUMERIC(6,4) (2 digits to the left of the point and 4 to the 
righ) and a NUMERIC(7,2) (5 digits to the left of the point and 2 to the 
right), what precision is the result?  NUMERIC(4,2) (2 digits to the left 
of the point and 2 to the right)?  NUMERIC(9,4) (5 digits to the left of 
the point and 4 digits to the right)?  How does roundoff work?  If I take 
the NUMERIC(6,4) number 62.0000 and multiply it by the NUMERIC(6,4) number 
02.0000, what answer do I get?  The NUMERIC(6,4) number 24.000?  The 
NUMERIC(7,4) number 124.000?  Or does it throw an exception?

>
> There doesn't seem to me to be a good natural map for this type in the
> stdlib.

If decimal roundoff isn't important, I'd be tempted to go for floats.  I 
don't know if this is true or not.

Brian


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] What library to use for arbitrary precision decimals
  2006-02-19 16:53     ` Brian Hurt
@ 2006-02-19 17:00       ` Richard Jones
  2006-02-19 17:13         ` Richard Jones
  0 siblings, 1 reply; 9+ messages in thread
From: Richard Jones @ 2006-02-19 17:00 UTC (permalink / raw)
  To: Brian Hurt; +Cc: caml-list

On Sun, Feb 19, 2006 at 10:53:47AM -0600, Brian Hurt wrote:
> Hmm.  There are problems definin that library.  What are the semantics? 
> If I add a NUMERIC(6,4) (2 digits to the left of the point and 4 to the 
> righ) and a NUMERIC(7,2) (5 digits to the left of the point and 2 to the 
> right), what precision is the result?  NUMERIC(4,2) (2 digits to the left 
> of the point and 2 to the right)?  NUMERIC(9,4) (5 digits to the left of 
> the point and 4 digits to the right)?  How does roundoff work?  If I take 
> the NUMERIC(6,4) number 62.0000 and multiply it by the NUMERIC(6,4) number 
> 02.0000, what answer do I get?  The NUMERIC(6,4) number 24.000?  The 
> NUMERIC(7,4) number 124.000?  Or does it throw an exception?

Well yes indeed.  I'm quite sure there's a SQL specification somewhere
which answers this :-)

Rich.

-- 
Richard Jones, CTO Merjis Ltd.
Merjis - web marketing and technology - http://merjis.com
Team Notepad - intranets and extranets for business - http://team-notepad.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] What library to use for arbitrary precision decimals
  2006-02-19 17:00       ` Richard Jones
@ 2006-02-19 17:13         ` Richard Jones
  0 siblings, 0 replies; 9+ messages in thread
From: Richard Jones @ 2006-02-19 17:13 UTC (permalink / raw)
  To: caml-list


I checked the standard and for standard operations on NUMERIC, the
precision of the result is implementation defined, while the scale
depends on the operation:

 + -    S_r = max (S_1, S_2)
 *      S_r = S_1 + S_2
 /      S_r = implementation defined

where S_r = scale of the result, and S_1 = scale of the first operand
and S_2 = scale of the second operand.

Rich.

-- 
Richard Jones, CTO Merjis Ltd.
Merjis - web marketing and technology - http://merjis.com
Team Notepad - intranets and extranets for business - http://team-notepad.com


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] What library to use for arbitrary precision decimals
  2006-02-19 15:44 ` [Caml-list] " Brian Hurt
  2006-02-19 16:38   ` Richard Jones
@ 2006-02-19 17:21   ` Jeremy Shute
  2006-02-19 18:31     ` Brian Hurt
  1 sibling, 1 reply; 9+ messages in thread
From: Jeremy Shute @ 2006-02-19 17:21 UTC (permalink / raw)
  To: Brian Hurt; +Cc: Joshua Smith, caml-list

[-- Attachment #1: Type: text/plain, Size: 2991 bytes --]

If you use the Int64 module as the basis for your computations, you can
hold values up to $184,467,440,737,095.51 in size.

How many Vietnamese Dongs is that?  Some CIA factbook estimates of the GDP
of the world:

$US 5.938e+13

One dollar will buy you a lot of Vietnamese Dongs:

$VND 1.5838e+4

So, the GDP of the world (a popular number, to be sure) is about:

$VND 9.4046e+17

...and the the max signed int64 is around...

9.2234e+18

This is not an isolated case, there are quite a few currencies in the $? 10K
/ $US 1 range.  Point: you're one locale change and some depreciation away
from overflowing when someone wants to calculate a ratio for analysis.  Why
not use a big int?

If you're keeping things in a database, you're going to be spending
milliseconds skipping across the disk for this and that -- what's the point
of placing an arbitrary limit on the size?  If the profiler shows that
you're eating cycles like candy, optimize your routine back down.

Jeremy



On 2/19/06, Brian Hurt <bhurt@spnz.org> wrote:
>
>
>
> On Sun, 19 Feb 2006, Joshua Smith wrote:
>
> > There are a couple of ways to handle money transactions without
> > rounding errors.
> >
> > You could use the Nums library, which provides arbitrary precision
> > calculations and numbers.   But even with arbitrary precision numbers,
> > you still can have the situation where you get 405.0345 which if this
> > were USD, you would still have to round if you wanted to pay someone
> > this amount.  You will still have the arbitrary precision this way,
> > however.
> >
> > The best way to handle money (in my experience) is to use integers.
> > Then you can define conversion functions but only have to convert it
> > to decimal for display purposes.  That way, even if you do a million
> > transactions you won't lose any information.   You can also handle
> > non-decimal based currencies/instruments/transactions that way[1]
>
> I agree with this recommendation.  The basic idea is that you use fixed
> point.  Say you want to be accurate to one thousandth of a cent (0.001
> cents).  You simply do all calculations in terms of millicents.  So the
> integer 1 represents one millicent.  One penny is represented as the
> integer 1,000- one thousand millicents.  The amount $2,345.67 is
> represented by the integer 234,567,000.
>
> If you use the Int64 module as the basis for your computations, you can
> hold values up to $184,467,440,737,095.51 in size.  This is larger than
> the world's GDP, so it should be large enough.  32 bits isn't enough- that
> only allows you to hold values up to $42,949.67.
>
> Brian
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>

[-- Attachment #2: Type: text/html, Size: 3880 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] What library to use for arbitrary precision decimals
  2006-02-19 17:21   ` Jeremy Shute
@ 2006-02-19 18:31     ` Brian Hurt
  0 siblings, 0 replies; 9+ messages in thread
From: Brian Hurt @ 2006-02-19 18:31 UTC (permalink / raw)
  To: Jeremy Shute; +Cc: Joshua Smith, caml-list



On Sun, 19 Feb 2006, Jeremy Shute wrote:

> If you use the Int64 module as the basis for your computations, you can
> hold values up to $184,467,440,737,095.51 in size.
>
> How many Vietnamese Dongs is that?  Some CIA factbook estimates of the GDP
> of the world:
>
> $US 5.938e+13
>
> One dollar will buy you a lot of Vietnamese Dongs:
>
> $VND 1.5838e+4

>
> So, the GDP of the world (a popular number, to be sure) is about:
>
> $VND 9.4046e+17
>
> ...and the the max signed int64 is around...
>
> 9.2234e+18
>
> This is not an isolated case, there are quite a few currencies in the $? 10K
> / $US 1 range.  Point: you're one locale change and some depreciation away
> from overflowing when someone wants to calculate a ratio for analysis.  Why
> not use a big int?

You're right that if you're needing to calculate the World GDP, or even 
the American debt, you may need more bits.  Although I was doing stuff in 
millipennies, simply doing stuff in centipennies still leaves you enough 
information to round to the nearest penny correctly, and gives you another 
order of magnitude headroom.

The reason to use Int64 instead of Bigint is performance.  This may or may 
not be an issue.  Although I note that both Bigint and Int64 performance 
is going to way stomp BCD performance.

Brian


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Caml-list] What library to use for arbitrary precision decimals
  2006-02-19 10:18 Richard Jones
@ 2006-02-19 14:03 ` Christophe TROESTLER
  0 siblings, 0 replies; 9+ messages in thread
From: Christophe TROESTLER @ 2006-02-19 14:03 UTC (permalink / raw)
  To: Richard Jones; +Cc: OCaml Mailing List

On Sun, 19 Feb 2006, Richard Jones <rich@annexia.org> wrote:
> 
> What library / type should I be using for arbitrary precision decimals
> - ie. floats where I can store things like currency amounts without
> getting rounding errors?

For some time I have been thinking to implement the following
spec. but I never found the time...

http://72.14.207.104/search?q=cache:H663GV4FII4J:www2.hursley.ibm.com/decimal/+decimal+arithmetic&hl=en&ct=clnk&cd=1

Cheers,
ChriS


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2006-02-19 18:31 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-02-19 13:43 What library to use for arbitrary precision decimals Joshua Smith
2006-02-19 15:44 ` [Caml-list] " Brian Hurt
2006-02-19 16:38   ` Richard Jones
2006-02-19 16:53     ` Brian Hurt
2006-02-19 17:00       ` Richard Jones
2006-02-19 17:13         ` Richard Jones
2006-02-19 17:21   ` Jeremy Shute
2006-02-19 18:31     ` Brian Hurt
  -- strict thread matches above, loose matches on Subject: below --
2006-02-19 10:18 Richard Jones
2006-02-19 14:03 ` [Caml-list] " Christophe TROESTLER

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).