Re: Packed decimal arithmetic in C

From: David Froble (davef_at_tsoft-inc.com)
Date: 07/25/03


Date: Thu, 24 Jul 2003 20:45:30 -0400

Chris Scheers wrote:

> briggs@encompasserve.org wrote:
>
>>In article <3F1EE1FB.FE8CBFC4@istop.com>, JF Mezei <jfmezei.spamnot@istop.com> writes:
>>
>>>John Reagan wrote:
>>>
>>>>If they were only that smart... I've seen dozens of examples of people
>>>>using binary floating to track currency (and each one is broken). I've
>>>>even seen them in languages that provided scaled integers like BASIC.
>>>>
>>>Interesting since there are often standards on exactly how many decimals to
>>>use when specifying currency and conversion factors, as in the case of
>>>international SWIFT transactions. With floating point, you can't specify how
>>>many decimals to consider during arithmetic, only during display.
>>>
>>Ahhh. The point being that floating point considers _more_ digits
>>in some cases than the standards specify and thus gets the answer
>>"wrong" for that reason?
>>
>>Interesting.
>>
>>So if you were going to use floating point correctly in such a
>>case, one appropriate approach would be to use it to implement scaled
>>integers (make sure your integers fit into the mantissa, round to
>>nearest integer after multiplication or division and track the
>>decimal scale factor by hand). Right?
>>
>>I once used double precision floating point in exactly that manner.
>>It made sense since I had compiler and hardware support for D floating
>>arithmetic but no compiler or hardware support for 64 bit integer
>>arithmetic. 32 bit integers were too small, but the mantissa
>>on 64 bit floats was big enough for my purposes. If I were
>>re-implementing today, I'd be using 64 bit native integer arithmetic.
>>
>> John Briggs
>>
>
>
> To try to summarize the issues: (Hopefully I will get this mostly
> right. I apologize if I am rehashing the obvious.)
>
> For now, we are only considering financial applications, i.e.,
> applications that track currency and need to do so exactly.
>
> The first problem is exactness:
>
> 1) An integer is not appropriate for tracking currency as dollars, since
> an amount such as $1.35 can not be represented exactly.
>
> 2) A scaled integer consists of two values: the value and where the
> decimal point is (the scale). This is what you are used to seeing on a
> calculator display. A scaled integer represents $1.35 as 135s2, i.e.,
> 135 with the decimal point shifted left 2 (between the 1 and 3). This
> is also known as tracking pennies. Sometimes a scale larger than two is
> required. Quite often, compound interest calculations require a larger
> scale. Also, different currencies may have different requirements.
>
> A scaled integer meets the requirement of exactness.
>
> 3) A floating point number is not appropriate for currency calculations
> because a floating point number can not exactly represent 1.35. Getting
> technical, the problem is that the base used in floating point numbers
> is a power of two whereas currency calculations need a base that is a
> power of ten. In base 2, 1/10 is a repeating fraction and can not be
> represented accurately.
>
> A floating point number does not meet the requirement of exactness.
>
> 3) Comparing floating point and scaled integer, it may become obvious
> that a scaled integer is really a floating point number that is base 10
> instead of base 2. They are really implementations of the same thing,
> but scaled integers are more appropriate for financial applications.
>
> The second problem is range:
>
> 1) Using a scaled integers, some calculations can exceed the range
> available in 32 bits.
>
> 2) Decimal arithmetic is one solution to this. Decimal arithmetic
> tracks the number as a string of decimal digits. (Again, like a
> calculator.) Decimal numbers are scaled integers, but are not
> restricted to 32 bits. Generally, a decimal arithmetic implementation
> allows up to (at least) 31 digits.
>
> 3) Floating point is another solution to this problem. A floating point
> number is implemented as some number of bits for the power and some bits
> for the mantissa. The mantissa is the numeric part of the value. If
> the power is held at zero, the mantissa is the integer value of the
> number. (Ignoring normalization.) Basically, you use the floating
> point number to hold an integer.
>
> What's the point to this? Well, a 64 bit or 128 bit floating point
> value has more than 32 bits of mantissa. This allows the floating point
> value to hold an integer larger than 32 bits. You can also do math on
> this number with floating point instructions. Just manage the power
> appropriately. If this is done correctly, the floating point value
> becomes exact for our purposes. The extra bits give us the range we
> need. You still need to maintain an external scale. You have created a
> scaled integer with the integer part stored in a floating point value.
>
>
> Summary:
>
> Either an extended precision floating point value or a decimal variable
> can be used to provide a scaled integer with more than 32 bits of
> precision.
>
> COBOL and PL/I have built in support for decimal variables.
>
> The Alpha does not have hardware support for decimal variables, but does
> have hardware support for extended precision floating point values, so
> code can be more efficient. But code libraries need to be written to
> manipulate the floating point values as scaled integers.
>
> Summary #2:
>
> Native 64 bit integer support in the Alpha makes much of the preceding
> discussion moot, if you are writing new code.
>
> Let the discussion continue!

Ok.

I've found double precision floating point to be entirely adequate for storing
monetary amounts. I'll note that I've only used it for US$. I'll also note
that $1,000,000.00 is a rather large monetary amount for any of the work I've
done, and $100 million is more than ever required. I'll concede that there are
places where much more magnitude is required, while still requiring preciseness
to the penny.

As for calculations, that's a bit different. To do so, a programmer must
routinely perform a rounding calculation after, or as part of, any calculation,
or group of calculations. Sure, there are values that cannot exactly be
represented in a floating point number, but, what's the difference between 1.35
and 1.34999999999999? If an amount is added to this value, and the result is
rounded to 2 digits after the decimal point, that's adequate for counting
dollars and cents. Multiply it by 100, and still, what's the meaningful
difference between 134.99999999999 and 135? Once rounded, it becomes 135.

Dave

-- 
David Froble                       Tel: 724-529-0450
Dave Froble Enterprises, Inc.      Fax: 724-529-0596
DFE Ultralights, Inc.              E-Mail: davef@tsoft-inc.com
T-Soft, Inc.  170 Grimplin Road  Vanderbilt, PA  15486


Relevant Pages

  • Re: Packed decimal arithmetic in C
    ... With floating point, you can't specify how ... >> many decimals to consider during arithmetic, ... applications that track currency and need to do so exactly. ... A scaled integer consists of two values: ...
    (comp.os.vms)
  • RE: Packed decimal arithmetic in C
    ... >many decimals to ... >> I once used double precision floating point in exactly that manner. ... >applications that track currency and need to do so exactly. ... >A scaled integer meets the requirement of exactness. ...
    (comp.os.vms)
  • Re: Decimal: fixed-point or floating-point
    ... > If a Decimal is simply a scaled Integer (as opposed to floating point which ... The only reason that can't be done in floating binary point (as ... specified by IEEE 754) is normalisation, I think - the assumed 1 on the ... front of the fraction. ...
    (microsoft.public.dotnet.framework.clr)
  • Re: Errors cancel sometimes
    ... I thought that it was remarkable, so I'm remarking on it. ... Goldberg's "What Every Computer Scientist Should Know About Floating ... elements of accurate numerical calculations on a computer as well. ... I'd be happy to have any pointers to more modern works that cover the ...
    (comp.programming)
  • Re: TDD: Test-Driven Design or Test-Driven Development?
    ... design idea, and conflating it. ... > requires one to implement floating point calculations. ... This decision may affect how the calculations are coded. ... Please describe the Test Driven Development process that you think we are ...
    (comp.object)