470,596 Members | 1,200 Online

# prePEP: Money data type

Here I send it.

Suggestions and all kinds of recomendations are more than welcomed.

If it all goes ok, it'll be a PEP when I finish writing the code.

Thank you.

.. Facundo
------------------------------------------------------------------------

PEP: XXXX
Title: Money data type
Version: $Revision: 0.1$
Last-Modified: $Date: 2003/10/17 17:34:00$
Author: Facundo Batista <fb******@unifon.com.ar>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 17-Oct-2003
Python-Version: 2.3.3
Abstract
========

The idea is to make a Money data type, basically for financial uses, where
decimals are needed but floating point is too inexact. The Money data type
should support the Python standard functions and operations.
Rationale
=========

The detail of the requeriments are in the Requirements_ section. Here
I'll
include all the decisions made and why, and all the subjects still in
discussion. The requirements will be numbered, to simplify discussion on
each point.

As an XP exercise, I'll write the test cases before de class itself, so
it'll
comply exactly the requeriments of those tests. Please see them for an
exact
specification (and if you propose a different behaviour, please propose the
corresponding test case if possible, thanks).
Why Not To Use Tim Peters' FixedPoint?
--------------------------------------

As we'll see in Requeriments, thera are items that FixedPoint doesn´t comply
(because doesn't do something or does it different). It could be extended
or
modified to comply the Requeriments, but some needs are own to currency, and
some features of FixedPoint are too much for Money, so taking them out will
make this class simplier.

Anyway, sometime maybe one could be made subclass of the other, or just make
one from both. The code of the Money class is based in large part on the
code of Tim Peters' FixedPoint: thank you for your (very) valuable ideas.
Items In Discussion
-------------------

6. About repr(). Should myMoney == eval(repr(myMoney))?
Requirements
============

1. The sintaxis should be Money(value, [precision]).

2. The value could of the type:

- another money (if you don't include *precision*, it get
inheritated)

- int or long (default *precision*: 0)::

Money(45): 45
Money(45, 2): 45.00
Money(5000000000,3): 5000000000.000

- float (*precision* must be included)::

Money(50.33, 3): 50.330

- string (*precision* get extracted from the string)::

Money('25.32'): 25.32
Money('25.32', 4): 25.3200

- something that could be coerced by long() or float()

3. Not to support strings with engineer notation (you don't need this when
using money).

4. Precision must be a non negative integer, and after created the object
you could not change it.

5. Attributes decimalSeparator, currencySymbol and
thousandSeparator could be overloaded, just to easy change them
subclassing. This same *decimalSeparator* is that used by the constructor
when receives a string. Defaults are::

decimalSeparator = '.'
currencySimbol = '$' thousandSeparator = '' 6. Calling repr() should not return str(self), because if the subclass indicates that decimalSeparator='', this could carry to a confusion. So, repr() should show a tuple of three values: IntPart, FracPart, Precision. 7. To comply the test case of Mark McEahern:: cost = Money('5.99') percentDiscount = 10 months = 3 subTotal = cost * months discount = subTotal * (percentDiscount * 1.0) / 100 total = subTotal - discount assertEqual(total, Money('16.17')) 8. To support the basic aritmetic (+, -, *, /, //, **, %, divmod) and the comparisons (==, !=, <, >, <=, >=, cmp) in the following cases: - Money op Money - Money op otherType - otherType op Money - Money op= otherType OtherType could be int, float or long. Automaticlly will be converted to Money, inheritating the precision from the other component of the operation (and, in the case of the float, maybe losing precision **before** the operation). When both are Moneys, the result has the larger precision from both. 9. To support unary operators (-, +, abs). 10. To support the built-in methods: - min, max - float, int, long (int and long are rounded by Money) - str, repr - hash - copy, deepcopy - bool (0 is false, otherwise true) 11. To have methods that return its components. The value of Money will be (int part) + (frac part) / (10 ** precision). - getPrecision(): the precision - getFracPart(): the fractional part (as long) - getIntPart(): the int part (as long) 12. The rounding to be financial. This means that to round a number in a position, if the digit at the right of that position is bigger than 5, the digit at the left of that position is incremented by one, if it's smaller than 5 isn't:: 1.123 --> 1.12 1.128 --> 1.13 But when the digit at the right of that position is ==5. There, if the digit at the left of that position is odd, it gets incremented, otherwise isn't:: 1.125 --> 1.12 1.135 --> 1.14 Reference Implementation ======================== To be included later: - code - test code - documentation Copyright ========= This document has been placed in the public domain. Jul 18 '05 #1 24 3297 I've made a few edits for spelling and grammar, but I haven't cleaned up everything, and I haven't made any substantive changes to the text. Do with it what you will. Substantive issues: 1. I've seen lots of strange rounding policies in various nooks and crannies. Is there any way of specifying a rounding policy that would be used and inherited by the result money object? 2. Money objects are presumably immutable, the same as all other numeric objects. I've edited item 4 to presume this. 3. I haven't looked at Tim Peter's fixed point module, so I don't know how he handled this. Formatting characters should come from the current locale, or else should be supplied by an extended format method. In fact, I'd make this a requirement: there should be a formatting method that would handle the most common commercial formatting requirements, including zero and asterisk fill, floating and fixed currency symbol, and blanking the entire output field when it is zero. Also trailing minus sign, and so forth. 4. Repr should round trip. That's basic Python. This means that repr() should return something that the money() constructor understands regardless of the current locale setting. Making it human readable is the responsibility of either str(), the % operator or a hypothetical ..printf() method. 6. On operators. What happens to precision on multiplication and division? John Roth "Batista, Facundo" <FB******@uniFON.com.ar> wrote in message news:ma*************************************@pytho n.org... Here I send it. Suggestions and all kinds of recomendations are more than welcomed. If it all goes ok, it'll be a PEP when I finish writing the code. Thank you. .. Facundo ------------------------------------------------------------------------ PEP: XXXX Title: Money data type Version:$Revision: 0.1 $Last-Modified:$Date: 2003/10/17 17:34:00 $Author: Facundo Batista <fb******@unifon.com.ar> Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 17-Oct-2003 Python-Version: 2.3.3 Abstract ======== The idea is to make a Money data type, basically for financial uses, where decimals are needed but floating point is too inexact. The Money data type should support the Python standard functions and operations. Rationale ========= The detail of the requeriments are in the Requirements_ section. Here I'll include all the decisions made and why, and all the subjects still being discussed. The requirements will be numbered, to simplify discussion on each point. As an XP exercise, I'll write the test cases before the class itself, so it'll comply exactly the requeriments of those tests. Please see them for an exact specification (and if you propose a different behaviour, please propose the corresponding test case if possible, thanks). Why Not Use Tim Peters' FixedPoint? -------------------------------------- As we'll see in Requeriments, there are items that FixedPoint does not satisfy, either because it doesn't do something or does it differently. It could be extended or modified to comply with the Requeriments, but some needs are specific to currency, and some features of FixedPoint are unnecessarilly complex for Money, so taking them out will make this class simplier. Anyway, sometime maybe one could be made subclass of the other, or just make one from both. The code of the Money class is based in large part on the code of Tim Peters' FixedPoint: thank you for your (very) valuable ideas. Open Issues ------------------- 6. About repr(). Should myMoney == eval(repr(myMoney))? Requirements ============ 1. The syntax should be Money(value, [precision]). 2. The value is one of the following: - another money (if you don't include *precision*, it will be inheritated) - int or long (default *precision*: 0):: Money(45): 45 Money(45, 2): 45.00 Money(5000000000,3): 5000000000.000 - float (*precision* is required):: Money(50.33, 3): 50.330 - string (*precision* is extracted from the string):: Money('25.32'): 25.32 Money('25.32', 4): 25.3200 - any other object that could be input to the long() or float() constructors. 3. Strings with floats in engineering notation will not be supported. This is an unecessary complication. 4. Precision must be a non negative integer. 5. Attributes decimalSeparator, currencySymbol and thousandSeparator could be overloaded, just to easy change them subclassing. This same *decimalSeparator* is that used by the constructor when receives a string. Defaults are:: decimalSeparator = '.' currencySimbol = '$'
thousandSeparator = ''

6. Calling repr() should not return str(self), because if the subclass
indicates that decimalSeparator='', this could carry to a confusion.
So, repr() should show a tuple of three values: IntPart, FracPart,
Precision.

7. To comply the test case of Mark McEahern::

cost = Money('5.99')
percentDiscount = 10
months = 3
subTotal = cost * months
discount = subTotal * (percentDiscount * 1.0) / 100
total = subTotal - discount
assertEqual(total, Money('16.17'))

8. To support the basic aritmetic (+, -, *, /, //, **, %, divmod) and
comparison (==, !=, <, >, <=, >=, cmp) operators in the following cases:

- Money op Money
- Money op otherType
- otherType op Money
- Money op= otherType

OtherType could be int, float or long. Automaticlly will be converted to
Money, inheritating the precision from the other component of the
operation (and, in the case of the float, maybe losing precision
**before** the operation).

When both are Moneys, the result has the larger of the two precisions.

9. To support unary operators (-, +, abs).

10. To support the built-in methods:

- min, max
- float, int, long (int and long are rounded by Money)
- str, repr
- hash
- copy, deepcopy
- bool (0 is false, otherwise true)

11. To have methods that return its components. The value of Money will be
(int part) + (frac part) / (10 ** precision).

- getPrecision(): the precision
- getFracPart(): the fractional part (as long)
- getIntPart(): the int part (as long)

12. The rounding to be financial. This means that to round a number in a
position, if the digit at the right of that position is bigger than 5,
the digit at the left of that position is incremented by one, if it's
smaller than 5 isn't::

1.123 --> 1.12
1.128 --> 1.13

But when the digit at the right of that position is ==5. There, if the
digit at the left of that position is odd, it gets incremented,
otherwise
isn't::

1.125 --> 1.12
1.135 --> 1.14
Reference Implementation
========================

To be included later:

- code
- test code
- documentation
=========

This document has been placed in the public domain.
Jul 18 '05 #2
John Roth wrote:
I've made a few edits for spelling and grammar, but I
haven't cleaned up everything, and I haven't made
any substantive changes to the text. Do with it what
you will.

Substantive issues:

1. I've seen lots of strange rounding policies in
various nooks and crannies. Is there any way of
specifying a rounding policy that would be used
and inherited by the result money object?

Amen, Hallelujah. I've followed up to Batista's similar
post to python-dev by pointing out chapter and verse of
EU regulations that _mandate_ "rounding to nearest and
always round exactly-halfway UPWARDS", for example.

As a side note, it's quite possible to spend inordinate
amounts of attention on formatting. I would suggest that
a fundamental 'money' class should first of all nail down
the *computation* issues (just that variety of rounding
specs is gonna be SUCH a bear...!) and receiving and
returning information. Once that is done, one or more
formatting functions can always be developed, be it as
methods of the money class, a subclass, or whatever. No
matter how it may look from Cobol, RPG, etc, correct and
accurate computation that respects all relevant fiddly
accounting regulations and practices IS the essence --
formatting requirements vary widely, and, if the base class
does arithmetic "right" AND allows complete receiving and
returning of information, extra formatting niceties can
always be "plugged on top" later. But if the arithmetic
is creaky -- e.g., _VB_'s "money" type -- all the cutesy
formatting in the world won't ever fix it.
Alex

Jul 18 '05 #3
You're right, Alex, in that arithmetic is the real issue to be addressed,
not formatting..

I also wonder if computation error should be tracked with this class, i.e.
when you assign a Money type value of 1.21 then you know that the error is
0.05 at most.
After that the usual error propagation rules apply for the arithmetic
operations..

Best,
Miklós
--
PRISZNYÁK Miklós
---
Jegenye 2001 Bt. ( mailto:je*********@parkhosting.com )
Custom software development, consulting
http://jegenye2001.parkhosting.com
Alex Martelli <al***@aleax.it> wrote in message
news:Hg*******************@news1.tin.it...
John Roth wrote:
Substantive issues:

1. I've seen lots of strange rounding policies in
various nooks and crannies. Is there any way of
specifying a rounding policy that would be used
and inherited by the result money object?

As a side note, it's quite possible to spend inordinate
amounts of attention on formatting. I would suggest that
a fundamental 'money' class should first of all nail down
the *computation* issues (just that variety of rounding
specs is gonna be SUCH a bear...!) and receiving and
returning information. Once that is done, one or more
formatting functions can always be developed, be it as
methods of the money class, a subclass, or whatever. No
Alex

Jul 18 '05 #4
Jegenye 2001 Bt wrote:
You're right, Alex, in that arithmetic is the real issue to be addressed,
not formatting..

I also wonder if computation error should be tracked with this class, i.e.
when you assign a Money type value of 1.21 then you know that the error
is 0.05 at most.
After that the usual error propagation rules apply for the arithmetic
operations..

That's not the way accountants do it in most situations. I think a numeric
class with explicit error bounds and propagations may have its place, but
that place is not as "the" type recommended for money computations in
most Python application programs, IMHO.
Alex

Jul 18 '05 #5
Alex Martelli <al***@aleax.it> writes:
1. I've seen lots of strange rounding policies in various nooks
and crannies. Is there any way of specifying a rounding policy
that would be used and inherited by the result money object?

Amen, Hallelujah. I've followed up to Batista's similar post to
python-dev by pointing out chapter and verse of EU regulations that
_mandate_ "rounding to nearest and always round exactly-halfway
UPWARDS", for example.

decimal arithmetic had been done in Cobol since the 1950's. They
haven't gotten this stuff figured out by now? Can you crunch some
calculation through a Cobol program and get an answer thtat's correct
in the US and wrong in the EU?
Jul 18 '05 #6
Ok, I'm not the accountant type. :D
I'm an ex-physicist. ;) That's why I find controlled error bounds important.

Best,
Miklós

Alex Martelli <al***@aleax.it> wrote in message
news:5J*******************@news1.tin.it...
That's not the way accountants do it in most situations. I think a numeric class with explicit error bounds and propagations may have its place, but
that place is not as "the" type recommended for money computations in
most Python application programs, IMHO.
Alex

Jul 18 '05 #7

"Paul Rubin" <http://ph****@NOSPAM.invalid> wrote in message
news:7x************@ruckus.brouhaha.com...
Alex Martelli <al***@aleax.it> writes:
1. I've seen lots of strange rounding policies in various nooks
and crannies. Is there any way of specifying a rounding policy
that would be used and inherited by the result money object?

Amen, Hallelujah. I've followed up to Batista's similar post to
python-dev by pointing out chapter and verse of EU regulations that
_mandate_ "rounding to nearest and always round exactly-halfway
UPWARDS", for example.

decimal arithmetic had been done in Cobol since the 1950's. They
haven't gotten this stuff figured out by now? Can you crunch some
calculation through a Cobol program and get an answer that's correct
in the US and wrong in the EU?

COBOL's default rounding policy is to truncate. It has a second
rounding policy that is invoked by the keyword ROUND (surprise,
eh?) However, one of the things that COBOL arithmetic has is
precise control of the number of decimal places at all points in
a computation[1], so if you don't like either truncation or the effects
of ROUND, then you simply maintain an additional decimal place
or two and do it your way.[2]

The difficulty here is that the control is maintained by declaring
what the *output* of an operation looks like, and that's
pretty much impossible for a language that doesn't have
declarations.

John Roth
(who hopes to never see another COBOL program in his life -
unless you're paying him big bucks, of course... [grin])

[1] Unless, of course, you're using the COMPUTE verb.

[2] Unless that would run you over 18 digits. Why 18, I
have no idea, and I'm afraid that most of the people on the
original COBOL committee are no longer with us.
Jul 18 '05 #8
"John Roth" <ne********@jhrothjr.com> writes:
COBOL's default rounding policy is to truncate. It has a second
rounding policy that is invoked by the keyword ROUND (surprise,
eh?) However, one of the things that COBOL arithmetic has is
precise control of the number of decimal places at all points in
a computation[1], so if you don't like either truncation or the effects
of ROUND, then you simply maintain an additional decimal place
or two and do it your way.[2]
Yeah, but what about the exact method of rounding, like the pre-PEP
specifies 1.125 rounds down but 1.135 rounds up (or maybe it was the
other way), while some other standard specifies always rounding down
(or up) when the extra digit is a 5.
[2] Unless that would run you over 18 digits. Why 18, I
have no idea, and I'm afraid that most of the people on the
original COBOL committee are no longer with us.

That's obvious, it's how many BCD digits would fit in a doubleword of
the 36-bit machines in use at that time.
Jul 18 '05 #9
Paul Rubin wrote:
"John Roth" <ne********@jhrothjr.com> writes:
COBOL's default rounding policy is to truncate. It has a second
rounding policy that is invoked by the keyword ROUND (surprise,
eh?) However, one of the things that COBOL arithmetic has is
precise control of the number of decimal places at all points in
a computation[1], so if you don't like either truncation or the effects
of ROUND, then you simply maintain an additional decimal place
or two and do it your way.[2]

Yeah, but what about the exact method of rounding, like the pre-PEP
specifies 1.125 rounds down but 1.135 rounds up (or maybe it was the
other way), while some other standard specifies always rounding down
(or up) when the extra digit is a 5.

Round-to-even-cent is quite popular (Roguewave calls it "Banker's
Rounding" in the Money class of their commercial class library).
So is always-round-up (again in the case in which an exact
computation would end up with a half cent, or whatever other
least significant unit of measure), which Roguewave calls "Plain
Rounding", and the European Union specifies.

If you have a type that only performs one kind of rounding, you
cannot use that type for legally valid money computations in
both Europe AND America (I think: I haven't been shown American
laws specifying rounding approaches, have just seen that "round
to even" mentioned as being usual, habitual, or popular).
Alex

Jul 18 '05 #10

"Paul Rubin" <http://ph****@NOSPAM.invalid> wrote in message
news:7x************@ruckus.brouhaha.com...
"John Roth" <ne********@jhrothjr.com> writes:
COBOL's default rounding policy is to truncate. It has a second
rounding policy that is invoked by the keyword ROUND (surprise,
eh?) However, one of the things that COBOL arithmetic has is
precise control of the number of decimal places at all points in
a computation[1], so if you don't like either truncation or the effects
of ROUND, then you simply maintain an additional decimal place
or two and do it your way.[2]

Yeah, but what about the exact method of rounding, like the pre-PEP
specifies 1.125 rounds down but 1.135 rounds up (or maybe it was the
other way), while some other standard specifies always rounding down
(or up) when the extra digit is a 5.

Like I said, you do it your way. That is, write the necessary COBOL
code to round it the way you want. Ths is not as easy as it sounds
since COBOL is completely lacking in the basic abstraction facilities
such as subroutines with parameters within a single Procedure Division.

John Roth
Jul 18 '05 #11

"Alex Martelli" <al***@aleax.it> wrote in message
news:dY*******************@news1.tin.it...
Paul Rubin wrote:
"John Roth" <ne********@jhrothjr.com> writes:
COBOL's default rounding policy is to truncate. It has a second
rounding policy that is invoked by the keyword ROUND (surprise,
eh?) However, one of the things that COBOL arithmetic has is
precise control of the number of decimal places at all points in
a computation[1], so if you don't like either truncation or the effects
of ROUND, then you simply maintain an additional decimal place
or two and do it your way.[2]
Yeah, but what about the exact method of rounding, like the pre-PEP
specifies 1.125 rounds down but 1.135 rounds up (or maybe it was the
other way), while some other standard specifies always rounding down
(or up) when the extra digit is a 5.

Round-to-even-cent is quite popular (Roguewave calls it "Banker's
Rounding" in the Money class of their commercial class library).
So is always-round-up (again in the case in which an exact
computation would end up with a half cent, or whatever other
least significant unit of measure), which Roguewave calls "Plain
Rounding", and the European Union specifies.

If you have a type that only performs one kind of rounding, you
cannot use that type for legally valid money computations in
both Europe AND America (I think: I haven't been shown American
laws specifying rounding approaches, have just seen that "round
to even" mentioned as being usual, habitual, or popular).

I don't think there is any consistent law covering the matter in the
US. I do know that lots of taxes come with their own tables,
calculated to the penny, and don't come with directives on how
to calculate them for yourselves.

John Roth

Alex

Jul 18 '05 #12
Jegenye 2001 Bt wrote:
Ok, I'm not the accountant type. :D
I'm an ex-physicist. ;) That's why I find controlled error bounds
important.

But would you be happy if your bank statement reassured you that
your balance is "somewhere between 708.97 and 709.12 Euros"...?-)
Alex

Jul 18 '05 #13
"John Roth" <ne********@jhrothjr.com> writes:
Like I said, you do it your way. That is, write the necessary COBOL
code to round it the way you want. Ths is not as easy as it sounds
since COBOL is completely lacking in the basic abstraction facilities
such as subroutines with parameters within a single Procedure Division.

That's bizarre, is it really done like that in the actual real world?!
statement acts differently depending on how you've implemented
rounding?
Jul 18 '05 #14
Paul Rubin wrote:
Alex Martelli <al***@aleax.it> writes:
> 1. I've seen lots of strange rounding policies in various nooks
> and crannies. Is there any way of specifying a rounding policy
> that would be used and inherited by the result money object?
Amen, Hallelujah. I've followed up to Batista's similar post to
python-dev by pointing out chapter and verse of EU regulations that
_mandate_ "rounding to nearest and always round exactly-halfway
UPWARDS", for example.

decimal arithmetic had been done in Cobol since the 1950's. They

They have (at least since the early '60s -- not sure when Cobol
was first released) but the accountants have not necessarily been
happy with their treatment of cents.
haven't gotten this stuff figured out by now? Can you crunch some
calculation through a Cobol program and get an answer thtat's correct
in the US and wrong in the EU?

Definitely, given that the US and EU have different laws: if your
program gives the same answers in both places, cases can surely be
found where the answer is wrong (and at least in the EU case illegal;
I don't know if the matter is regulated by law in the US) in at
least one of the two places.

Until and unless somebody bangs EU and US legislators' heads
together, and forces them to agree on one common standard for
accounting (down to such details as how to round half cents),
I don't see what programmers, as such, can do about it -- except
keep their software customizable in such variant-by-jurisdiction
respects:-(.
Alex

Jul 18 '05 #15
Paul Rubin wrote:
"John Roth" <ne********@jhrothjr.com> writes:
Like I said, you do it your way. That is, write the necessary COBOL
code to round it the way you want. Ths is not as easy as it sounds
since COBOL is completely lacking in the basic abstraction facilities
such as subroutines with parameters within a single Procedure Division.

That's bizarre, is it really done like that in the actual real world?!
statement acts differently depending on how you've implemented
rounding?

belief that a decent Martini cocktail is somehow automatically obtained
by "adding gin to vermouth" IS quite an apt simile (there's about six
bars here in Bologna I can count on to serve decent Martini cocktails:
the other hundreds of bars subscribe to the "Cobol arithmetic" approach:-).
Alex

Jul 18 '05 #16

"Paul Rubin" <http://ph****@NOSPAM.invalid> wrote in message
news:7x************@ruckus.brouhaha.com...
"John Roth" <ne********@jhrothjr.com> writes:
Like I said, you do it your way. That is, write the necessary COBOL
code to round it the way you want. Ths is not as easy as it sounds
since COBOL is completely lacking in the basic abstraction facilities
such as subroutines with parameters within a single Procedure Division.

That's bizarre, is it really done like that in the actual real world?!
statement acts differently depending on how you've implemented
rounding?

It has builtin arithmetic, including its own version of rounding. Operator
and I'm certain that the Navy wouldn't have accepted it if they had; their
concern was to get something out of draftees on a two year enlistment.

If I had to implement an odd rounding policy like: if the last digit is 4 or
greater, round up, then I'd have to do the add into a (not so) temporary
variable, and then follow it with the necessary code to do the round.
In practice, the COBOL coder would do the add into a specified variable,
then invoke (PERFORM) a parameterless subroutine to do the rounding
into another variable, and finally copy (MOVE) that temporary into its
final resting place.

If you've never done COBOL, you have no idea how absolutely clueless
the language is compared to even the most impoverished Algol class language.
It's still around partially because of PHB momentum, but also because
mainline languages have never discovered that fixed length character fields
and precise control of decimal arithmetic are highly beneficial for certain
kinds of applications.

One of the few benefits of static typing is that type declarations can
include
things like precision (part of COBOL and PL/1) and rounding policy (which
is not part of either language.)

This is why money types, like date types[1], aren't standard. There's too
much
variance in how you have to handle the details to admit of standardization
into
a one-size-fits-all solution.

John Roth

[1] Date types are hard to get right, as the new date module in 2.3
demonstrated.
The arbitrary choice of 1AD as the oldest date that could be handled makes
an otherwise admirable piece of work completely useless for my purposes,
and removes what would be a major reason for me to migrate my personal
programs to 2.3.

Jul 18 '05 #17
John Roth fed this fish to the penguins on Saturday 18 October 2003
08:51 am:

[2] Unless that would run you over 18 digits. Why 18, I
have no idea, and I'm afraid that most of the people on the
original COBOL committee are no longer with us.
Is that 18 /after/ the decimal, or 18 in total?

I recall that my college machine had hardware for BCD arithmetic (that
board failed one term -- FORTRAN classes were not affected as the
integer and float ALUs were still working, but COBOL classes were quite
late on assignments). The BCD unit used four normal registers to hold a
value -- 16 bytes. 16 bytes supported a 32 digit BCD number (actually,
I think it was 31 digits and a marker for sign/decimal place; as I
recall, the sign position floated as needed for the data).

-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <

Jul 18 '05 #18
Paul Rubin fed this fish to the penguins on Saturday 18 October 2003
10:59 am:

That's bizarre, is it really done like that in the actual real world?!
statement acts differently depending on how you've implemented
rounding?
By default, COBOL truncates when storing to a field with less
precision. So... To implement any specific rounding algorithm requires
performing the math using intermediates defined with the extra
place(s), and finishing with something like an IF <whatever condition>
ADD 0.xxxx5 to INTERMEDIATE (xxxx representing the 0s needed for the
precision of the intermediate) with a final MOVE INTERMEDIATE TO FINAL
(where final is defined with the precision of the "rounded" values).

Your "add gin to vermouth giving martini" would, in all likelihood, be
performed by zero-extending the less precise of gin|vermouth,
performing the add, then moving the result to martini -- truncating as
needed unless martini had been declared as a ROUNDED field, in which
case it is rounded up (the text book wasn't quite clear on if the
rounding was based on .5 of the least significant place, or any
non-zero value went up... "up" being relative to absolute value -- the
text book gave an example of something like -7.86 rounds to -7.9)
-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <

Jul 18 '05 #19

"Dennis Lee Bieber" <wl*****@ix.netcom.com> wrote in message
news:ob************@beastie.ix.netcom.com...
John Roth fed this fish to the penguins on Saturday 18 October 2003
08:51 am:

[2] Unless that would run you over 18 digits. Why 18, I
have no idea, and I'm afraid that most of the people on the
original COBOL committee are no longer with us.

Is that 18 /after/ the decimal, or 18 in total?

18 in total. I'm sure that one of the other poster's comment about
machines with 36 bit words was correct. It caused quite a bit
of difficulty since IBM's mainframes only handled 15 digits of
precision in the native decimal arithmetic. The compilers could
handle 18, but they had to use inline multiple precision routines to
do it.

John Roth
Jul 18 '05 #20
<posted & mailed>

Alex Martelli fed this fish to the penguins on Saturday 18 October 2003
11:11 am:

They have (at least since the early '60s -- not sure when Cobol
was first released) but the accountants have not necessarily been
happy with their treatment of cents.
My memory is failing, but I think FORTRAN predates COBOL by a few
years... I think CODASYL got the first COBOL spec out around 1961. The
language was standardized around 68 (74, 85, 2000?)

Until and unless somebody bangs EU and US legislators' heads
together, and forces them to agree on one common standard for
accounting (down to such details as how to round half cents),
I don't see what programmers, as such, can do about it -- except
keep their software customizable in such variant-by-jurisdiction
respects:-(.
I'd suspect the safest method would be to keep the data internally one
or two decimal places beyond that needed for the most precise currency
expected, and perform locale specific rounding only when reporting
values. (Something I suspect the Lockheed payroll system has to do, as
my current annual rate is 100,866.000000 [yes, the paycheck stub lists
6 decimal places!], which works out to an hourly rate of 48.493269xxx
-- if they'd rounded the latter before calculating the paycheck I'd be
cheated out of nearly $7 a year. Does make it painful to track in Quicken -- every week a different gross pay or tax deduction appears as the "error" for each item reaches the rounding "roll-over" point) -- ================================================== ============ < wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG < wu******@dm.net | Bestiaria Support Staff < ================================================== ============ < Bestiaria Home Page: http://www.beastie.dm.net/ < Home Page: http://www.dm.net/~wulfraed/ < Jul 18 '05 #21 John Roth fed this fish to the penguins on Saturday 18 October 2003 11:55 am: One of the few benefits of static typing is that type declarations can include things like precision (part of COBOL and PL/1) and rounding policy (which is not part of either language.) COBOL does have the ROUNDED keyword, though that isn't part of the declaration, but of the usage: add gin to vermouth giving martini {truncates} add gin to vermouth giving martini rounded {rounds, somehow} -- ================================================== ============ < wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG < wu******@dm.net | Bestiaria Support Staff < ================================================== ============ < Bestiaria Home Page: http://www.beastie.dm.net/ < Home Page: http://www.dm.net/~wulfraed/ < Jul 18 '05 #22 Dennis Lee Bieber fed this fish to the penguins on Saturday 18 October 2003 12:31 pm: needed unless martini had been declared as a ROUNDED field, in which Whoops, my first time through the book I thought ROUNDED applied to the field declaration, not to any specific operation... it goes on the math operation after naming the receiving field... -- ================================================== ============ < wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG < wu******@dm.net | Bestiaria Support Staff < ================================================== ============ < Bestiaria Home Page: http://www.beastie.dm.net/ < Home Page: http://www.dm.net/~wulfraed/ < Jul 18 '05 #23 "Dennis Lee Bieber" <wl*****@ix.netcom.com> wrote in message news:l5************@beastie.ix.netcom.com... <posted & mailed> Alex Martelli fed this fish to the penguins on Saturday 18 October 2003 11:11 am: They have (at least since the early '60s -- not sure when Cobol was first released) but the accountants have not necessarily been happy with their treatment of cents. My memory is failing, but I think FORTRAN predates COBOL by a few years... I think CODASYL got the first COBOL spec out around 1961. The language was standardized around 68 (74, 85, 2000?) Until and unless somebody bangs EU and US legislators' heads together, and forces them to agree on one common standard for accounting (down to such details as how to round half cents), I don't see what programmers, as such, can do about it -- except keep their software customizable in such variant-by-jurisdiction respects:-(. I'd suspect the safest method would be to keep the data internally one or two decimal places beyond that needed for the most precise currency expected, and perform locale specific rounding only when reporting values. (Something I suspect the Lockheed payroll system has to do, as my current annual rate is 100,866.000000 [yes, the paycheck stub lists 6 decimal places!], which works out to an hourly rate of 48.493269xxx -- if they'd rounded the latter before calculating the paycheck I'd be cheated out of nearly$7 a year. Does make it painful to track in
Quicken -- every week a different gross pay or tax deduction appears as
the "error" for each item reaches the rounding "roll-over" point)
Sometimes that's also a result of union negotions and interesting
policies to avoid losing cents to rounding errors. One way of handling
all of this is to always calcualte YTD and then subtract the prior YTD
to get current. Then there are interesting strategies to allocate the cents
to the workers on alternate weeks so that nobody files a union grievance...

John Roth

--
> ================================================== ============ <
> wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
> wu******@dm.net | Bestiaria Support Staff <
> ================================================== ============ <

Jul 18 '05 #24

Alex Martelli <al***@aleax.it> wrote in message
news:tb***********************@news2.tin.it...
Jegenye 2001 Bt wrote:

But would you be happy if your bank statement reassured you that
your balance is "somewhere between 708.97 and 709.12 Euros"...?-)
No, I'd be absolutely happy if the bank statement would contain that the
balance is
11101223.43* and this amount was computed by the publicly known and
standardized error propagation rules, so the bank
assures me the number cannot be less than 11101222.87 and it cannot be more
than 11101223.98 due to rounding numbers according to those rules.

* let's speak of a much nicer sum of money than that if it's about my
hypotetical bank account :-)

I know this is wishful thinking and even the bank employees would be
dazzled. ;(
Once I tried to explain to a gov. official that it doesn't matter at all if
unemployment is 15.1% or 14.9% in a certain region when he asked what that
$\sigma = 0.1%$
means next to 15% ... You cannot tell the real value only that it's between
those values with such and such probability. Ok, he understands. But is
unemployment high or low in that region according to law? (Which stated that
regions with enemployment higher than , say, 15% are entitled to certain
funds..)

This world is NOT the best world of all the possible worlds, Mr. Leibnitz.
;)

Cheers,
Miklós

--
PRISZNYÁK Miklós
---
Jegenye 2001 Bt. ( mailto:je*********@parkhosting.com )
Custom software development, consulting
http://jegenye2001.parkhosting.com

Alex

Jul 18 '05 #25

### This discussion thread is closed

Replies have been disabled for this discussion.