Boost logo

Boost :

From: George A. Heintzelman (georgeh_at_[hidden])
Date: 2001-05-09 12:48:31


I've often thought about writing this data type myself, so I would be
very interested in seeing it in boost.

> If there's interest, I'd like to do a reference implementation
> under the auspices of Boost. The requirements for the type
> would be:
>
> - A template class with the template parameter being the number
> of digits to the right of the decimal point.
>
> - Represent at least 18 decimal digits exactly. (The 18 comes
> from prior art on IBM mainframes, and also turns out to be
> convenient if the internal representation is a 64-bit int.)

Note that not all platforms support 64-bit ints directly. So you'll
have to do some work if you want to support 32-bit machines with this
requirement.

> - Support all operations that can be done on ints except implicit
> conversions and non-decimal I/O.

Yes, and you must be able to do binary operations with all numeric
types without having to do explicit type conversions; using a
float/double operand should give a float/double result, otherwise you
should get a fixed-point result. Note that supplying int versions and
not supplying double versions could give surprising results:
        fixed<2> n(14,23); // Say this is the constructor for 14.23
        cout << n * 2.3; // 28.46 or 32.729?

If you only supply fixed operator*(fixed,int), this will give you
something very different from what was probably wanted.

> - All operations are exact if there is no overflow and if no
> rounding is required. Overflow is undefined behavior.
> Rounding is done the way accountants do it: round to nearest
> with 1/2-LSB always rounded "up." (I think "up" means "away
> from zero." I've asked an accountant friend via e-mail but
> haven't yet gotten an answer.)

Accountants often do not round this way. They do what is known as the
banker's round, rounding an exact 1/2 LSB to the nearest even digit in
the higher place. This is to avoid, on the average, biases arising from
consistently rounding exact 1/2's (which happen frequently in finance)
'up' or 'down'. I think this rounding behavior would be a good choice
for this class.

> - Construction from const char* for faking decimal constants.

Interesting idea, but it should be an explicit constructor, and
presumably would be computationally expensive compared to building an
int or float from a constant, unless the compiler managed to optimize
it away (seems unlikely). So, I'd also be interested in other ways of
building it. For example:

typedef fixed<2> Money;
Money wallet(12,53); // Puts $12.53 in my wallet.
vector<Money> accounts(20,Money(252,20)); // Every player starts with
$252.20.

This would presumably give undefined results if the mantissa were
greater than 10^ndigits-1. I suspect that this kind of constructor,
which is just going to have a few inlined arithmetic operations, will
be easier for a compiler to optimize away into a fixed constant int
internally.

> - Explicit conversion to/from double.
>
> Are there more requirements that I haven't thought of?

Make sure that fixed<0> also works transparently (and doesn't append a
trailing radix character by default...). I don't want to have to
special-case currencies when I'm working in yen instead of pounds &
pence.

George Heintzelman
georgeh_at_[hidden]


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk