|
#1
|
|
|
|
|
This was posted on reddit --
http://cafe.elharo.com/programming/spot-the-bug/ Printed representations aside (that can be taken care of with ~$), how do you perform monetary calculations in CL? One way is to represent "cents" using integers. But what I would like to have is something like Python's decimal type [1]. I don't think standard CL supports anything like that. Is there any library, etc. which can do this? Or is Python's decimal type the wrong way to look? Is there anything better out there? Thanks, Chaitanya Note: 1. http://cafe.elharo.com/programming/spot-the-bug/ |
|
|
|
#2
|
|
|
|
|
Chaitanya Gupta wrote:
> One way is to represent "cents" using integers. But what I would like to > have is something like Python's decimal type [1]. > ... > Note: > 1. [..] Oops. That should have been: http://docs.python.org/lib/module-decimal.html Chaitanya |
|
#3
|
|
|
|
|
In article <fonjmb$kba$1>,
Chaitanya Gupta <mail> wrote: [..] > > Or is Python's decimal type the wrong way to look? Is there anything > better out there? > > Thanks, > > Chaitanya > > Note: > 1. [..] It might also be possible to use 'measures' for representing and handling monetary data. 'MEASURES is a system to handle engineering numbers and measures in Common Lisp.' http://www.cs.cmu.edu/afs/cs/project...easures/0.html LOOM has probably a newer version of measures. http://www.isi.edu/isd/LOOM/ |
|
#4
|
|
|
|
|
Rainer Joswig wrote:
> > It might also be possible to use 'measures' > for representing and handling monetary data. > Measures looks very interesting. Thanks for the link. |
|
#5
|
|
|
|
|
Chaitanya Gupta <mail> writes:
> Printed representations aside (that can be taken care of with ~$), how > do you perform monetary calculations in CL? It depends on your need. If you're just trying to work out how to manage your personal mortgage, and can accept slight discrepancies in exchange for speed and ease of use, floats would probably be fine. If you're trying to model the dynamics of world economies, which is fuzzy anyway, again floats are probably fine. Any use of floats would NOT be adequate to banks, since the roundoff would be too unpredictable. CL does not offer a packaged solution to that but does offer some useful tools. e.g., you could use a DOLLARS class that contained a slot that held an integer number of thousandths of pennies. And then write whatever methods on the class you wanted to be able to do. +$, *$, etc. Even if there were a "fixed decimal" type or something like that, you'd still have the issue of whether it was proper to do things like multiply that times another fixed decimal. Using the DOLLARS class, you could actually control it enough that it could add two DOLLARS classes but forbid you to add a regular integer to that class, or that could let you multiply DOLLARS times an integer, but not times DOLLARS. |
|
#6
|
|
|
|
|
On Feb 10, 11:35 am, Chaitanya Gupta <m> wrote:
> Printed representations aside (that can be taken care of with ~$), how > do you perform monetary calculations in CL? Chaitanya, I have a written a library whose express intent is supporting monetary calculations in Common Lisp. You can even do multi-currency calculations, in which case "balance" objects are creating which track the individual sub-totals of each currency. You can convert between currencies using a conversion price, and track the history of known prices in order to support historical reporting of market values. The library is called CAMBL, or the Commoditized Amounts and Balances Library, and you can find it here: http://hg.newartisans.com/cambl It depends on the LOCAL-TIME module (see Google), and also on two others modules which are also available on the same server: http://hg.newartisans.com/red-black http://hg.newartisans.com/periods The library is very close to its first release. I'm currently using it as the back-end for an accounting engine, CL-Ledger, which is also available at the same location. Note that even though it has not been formally released yet, the code is quite mature, as it represents a direct port from C++ of a library which has been in active use for over 4 years now. It comes with a suite of unit tests -- you will need XLUNIT to run them -- which you should use to verify its correctness on your platform. In case you're interested in the implementation, I use rational number to store all values, plus an integer to indicate how much floating- point precision to use when printing a particular currency. You don't have to explicitly specify the precision, either; the library observes the formatting you use when inputting numbers, and maintains this format automatically when outputting them. (There are also variants functions for inputting special numbers whose display characteristics should not be remembered, like dollar figures with more precision than 2 decimal places). There is preliminary usage documentation at the top of the Lisp file. I would be happy to work with you if changes are needed to suit the library to your needs. John |
|
#7
|
|
|
|
|
JohnW wrote:
> Chaitanya, I have a written a library whose express intent is > supporting monetary calculations in Common Lisp. You can even do > multi-currency calculations, in which case "balance" objects are > creating which track the individual sub-totals of each currency. You > can convert between currencies using a conversion price, and track the > history of known prices in order to support historical reporting of > market values. This is great. I just checked out cambl from the repository. Will try it and see how it works out. Is there any mailing list for the project? > The library is very close to its first release. I'm currently using > it as the back-end for an accounting engine, CL-Ledger, which is also > available at the same location. Note that even though it has not been > formally released yet, the code is quite mature, as it represents a > direct port from C++ of a library which has been in active use for > over 4 years now. Actually, I was looking at Ledger/CL-Ledger just a few weeks back. Never got around to installing it, but it has been on my todo list for sometime. Perhaps now I'll be able to take a look. ;) Chaitanya |
|
#8
|
|
|
|
|
Kent M Pitman wrote:
> > Any use of floats would NOT be adequate to banks, since the roundoff > would be too unpredictable. CL does not offer a packaged solution to > that but does offer some useful tools. e.g., you could use a DOLLARS > class that contained a slot that held an integer number of thousandths > of pennies. And then write whatever methods on the class you wanted > to be able to do. +$, *$, etc. > > Even if there were a "fixed decimal" type or something like that, > you'd still have the issue of whether it was proper to do things like > multiply that times another fixed decimal. Using the DOLLARS class, > you could actually control it enough that it could add two DOLLARS > classes but forbid you to add a regular integer to that class, or that > could let you multiply DOLLARS times an integer, but not times > DOLLARS. That's a very interesting way of handling it. I would certainly like to try it out. Also, is this technique being used widely? What could be the potential drawbacks of this? Chaitanya |
|
#9
|
|
|
|
|
On Feb 11, 11:32 am, Chaitanya Gupta <m> wrote:
> This is great. I just checked out cambl from the repository. Will try it > and see how it works out. Is there any mailing list for the project? There are web forums for the Ledger project at: http://forums.newartisans.com/ Anything posted here I usually respond to right away, since Apple Mail notifies me of all new posts along with my regular e-mail. Or, if you loathe web interfaces, just send me e-mail directly. I consider CAMBL "done" at this time, and so am highly motivated to weed out any final bugs before release. There is also a Trac for CL-Ledger, in which you could register CAMBL bugs and suggestions too: http://trac.newartisans.com/ledger You will need to register an account for both of these web services, since allowing public posting and bug creation was resulting in far too much spam. John |
|
#10
|
|
|
|
|
Chaitanya Gupta <mail> writes:
> Printed representations aside (that can be taken care of with ~$), how > do you perform monetary calculations in CL? > > One way is to represent "cents" using integers. But what I would like to > have is something like Python's decimal type [1]. I don't think standard > CL supports anything like that. Is there any library, etc. which can do > this? Well, another solution that works with standard Common Lisp datatypes would be to use rational numbers to represent your monetary values. Dollars, for example, would be integer values and the cents would be represented as the appropriate fractions. So, for example, you would write $5.27 as 527/100 or (+ 5 27/100) or even (rationalize 5.27). If you go the latter route, it is important to use RATIONALIZE rather than RATIONAL, since the former will give you a nicer rational number. |
|
#11
|
|
|
|
|
Thomas A. Russ wrote:
> Dollars, for example, would be integer values and the cents would be > represented as the appropriate fractions. So, for example, you would > write $5.27 as 527/100 or (+ 5 27/100) or even (rationalize 5.27). If > you go the latter route, it is important to use RATIONALIZE rather than > RATIONAL, since the former will give you a nicer rational number. Thanks for the heads up on RATIONALIZE/RATIONAL -- I didn't even know that these functions existed. Chaitanya |
|
#12
|
|
|
|
|
Chaitanya Gupta <mail> writes:
> Kent M Pitman wrote: > > That's a very interesting way of handling it. I would certainly like to > try it out. > > Also, is this technique being used widely? What could be the potential > drawbacks of this? > It sounds reasonable for accounting purposes but is insufficient for financial arithmetic- there are often rules for the application of things like yield rates that specify a number of places of precision and specific rules for rouding; for example, maintain 12 decimal places and round the 13th (by implication do not employ precision to more than the 13th place to the right of the decimal). Intermediate products of some calculations can easily consume 20 or more significant digits. Simple arithmetic on such calculations is inappropriate. Cobol handles this sort of thing quite well (intentionally I am sure). CL's numeric types will easily handle the required precision but the rounding rules will probably be somewhat troublesome. The class-based approach is probably the way to handle it- perhaps an "interest" class where the # of places of significance and the rounding policy are supplied. Gregm |
|
#13
|
|
|
|
|
På Thu, 14 Feb 2008 13:50:18 +0100, skrev Greg Menke <gusenet>:
> > It sounds reasonable for accounting purposes but is insufficient for > financial arithmetic- there are often rules for the application of > things like yield rates that specify a number of places of precision and > specific rules for rouding; for example, maintain 12 decimal places and > round the 13th (by implication do not employ precision to more than the > 13th place to the right of the decimal). Intermediate products of some > calculations can easily consume 20 or more significant digits. > > Simple arithmetic on such calculations is inappropriate. Cobol handles > this sort of thing quite well (intentionally I am sure). CL's numeric > types will easily handle the required precision but the rounding rules > will probably be somewhat troublesome. The class-based approach is > probably the way to handle it- perhaps an "interest" class where the # > of places of significance and the rounding policy are supplied. > > Gregm Well the most straightforward way is Binary Coded Decimal (BCD). One nibble (4 bits) is reserved for each digit 0-9. So you write a library to access numbers this way. (Many processors have support for this.) Writing such a library is a bit cumbersome, but still easier than dealing with the imprecision explicitly in bignums I would think. (Because humans think of precision in digits not binary) -------------- John Thingstad |
|
#14
|
|
|
|
|
"John Thingstad" <jpthing> writes:
> På Thu, 14 Feb 2008 13:50:18 +0100, skrev Greg Menke <gusenet>: >> Well the most straightforward way is Binary Coded Decimal (BCD). > One nibble (4 bits) is reserved for each digit 0-9. So you write a > library to access numbers this way. > (Many processors have support for this.) Writing such a library is a bit > cumbersome, but still easier than dealing with the imprecision > explicitly in bignums I would think. (Because humans think of precision > in digits not binary) Probably the easiest way would be to try and do it how COBOL does- since it was designed to handle this sort of problem. Its worth observing that when doing this kind of math, conformance to the specified rounding policy is far more important than speed, both in the operational sense, and when the time comes to audit the system, and maybe even more importantly when you have to start tracking down where the 1 cent error came from... This is perhaps an example of an "Anti-Greenspun Law", such as, "Any sufficiently complex financial application contains an ad-hoc, informally specified, bug ridden slow implementation of COBOL's fixed place numeric types". I've seen it happen on a number of occasions, and I've perpetrated it myself. Gregm |
|
#15
|
|
|
|
|
Rainer Joswig <joswig> writes:
> It might also be possible to use 'measures' > for representing and handling monetary data. > > 'MEASURES is a system to handle engineering numbers and measures in > Common Lisp.' > > [..] > > LOOM has probably a newer version of measures. > [..] It would certainly be possible to do that. One additional advantage of using the measures package is that one could then, in principle, also support multiple currencies and automatically convert between them. The only drawback is that the measures package assumes that conversion factors are constant, instead of fluctuating. Although one could keep redefining the conversions to track the market. Internally, the measures package uses rational numbers for everything (converted from decimal input using RATIONALIZE), just in order to avoid floating point rounding issues. People generally like it better if a units and measures package has 1mm*3.2 => 3.2mm instead of 3.2000002mm ;) |
|
|
|
|
| Similar Threads | |
| monetary values Why do monetary values show up as the pound sign's? |
|
| How do I add a column of monetary numbers I have a column of amounts of money. Just want excel to add them up and give me a total. |
|
| Matching a name to a specified monetary amount I need to find the formula that can match a specified monetary value to a name. For instance if I type in A1 Name1 then in B1 $14.00 comes in or if I would have typed in... |
|
| Monetary Format Hi, Well, I'm developing one application that will have support for many languages and countries, in the application I need to show and to format the currency for the chosen... |
|
| Help on Monetary figures Someone must know but not me. Can i get my figure amounts to only display to 2d.p. while it is linked back to an access dbase? Thanks in advance |
|
|
All times are GMT. The time now is 11:20 PM. | Privacy Policy
|