Boost logo

Boost :

From: Martin (adrianm_at_[hidden])
Date: 2005-01-08 09:36:48

(I know that "Currency" received 0 votes at the OOPSALA conference but maybe
someone is interested anyway)

I have implemented a type for handling decimal math and a type specialized for
monetary values.

decimal64 type
The type stores a decimal value with specified numberof decimals exactly and
also performs all arithmetic operations (+,-,*,/) using decimal math.

(Internally the type stores the value as an int64 value which gives 18 DECIMAL
digits precision. Multiply and divide uses a 128 bit temporay to avoid
rounding errors)

- All std rounding modes are available plus a few extra such as round_to_even.

- Construction of a decimal64 can be made from int, double, string literal
(e.g. "1.234") and other decimal64 values.

- Operations can be made on decimal64 objects with different number of
decimals and/or different rounding policy. Result of a binary operation on two
decimal64 values will have the number of decimals and rounding policy of the
left operand.

- Streaming works the same way as floating point values but the scientific
format is ignored.

There are 2 decimal64 types defined:

- decimal64 - all constructors requires specification of number of decimals
and optionally rounding mode.

decimal64(3.1415, 4, round_to_nearest);

- decimal64_spec - a template version of decimal64 where number of decimals
and rounding mode are specified as template parameters which allows a default

typedef decimal64_spec<3, round_to_even> decimal3;
decimal3 x(3.14), y;

The decimal value can be converted into another at any time if a calculation
needs to be performed at a higher precision or with another rounding policy.

decimal64 x(1.2, 1, round_to_nearest);

// calculate x*PI/2 using 5 decimals
// result is stored in x with 1 decimal,
// rounded with round_to_nearest policy

x = x.as_decimal(5) * decimal64(3.14159, 5) / 2;

Some things I would specificly like to have comments on:
1. Operations are not allowed on doubles. Double values always need to be
converted into a decimal value first. e.g. x * decimal64(3.14, 2). Is this
something that is needed?

2. No overflow detection or +inf etc. Just like with the integer types there
is no checking for overflow on operations.

Money type
The money type uses a decimal type to store a monetary value. The
functionality is the same as for the decimal64 type with the following

1. Operations are more limited to detect errors. The limitations are:
- Money * Money is not allowed. (Money * Decimal is allowed)
- Money / Money is allowed but the result is a Decimal (not money)
- Money + Decimal is not allowed (Money + Money is allowed).
  (The same applies to - and all comparison operators)

Integers works as both money and decimal so Money*2 and Money+1 is always

2. Streaming uses locale moneypunct for formatting and parsing.

As with the decimal type two money classes are defined

- money_base - construction always requires number of decimals and optionally
rounding policy

typedef money_base<decimal64> money64;
money64 x(100,2,round_toward_infinity);

- money_spec - number of decimals and rounding policy are template parameters.

typedef money_spec<decimal64, 4, round_toward_neg_infinity> money4;
money4 x("9.99"), y;

locale library
Some time ago implemented helper classes for locale but I never got around
submitting it to boost. I needed it for testing the decimal64/money streaming
so I cleaned it up and it is included in the package.

A jam file for building decimal library is included. I have compiled all files
and testcases with VS2002 (VC70) and "g++ (GCC) 3.4.2 (mingw-special)".
Couldn't get the boost test jam file to work but command line g++ works fine.
g++ libs/decimal/test/decimal64_test.cpp libs/decimal/src/decimal64.cpp
g++ libs/decimal/test/money_test.cpp libs/decimal/src/decimal64.cpp
g++ libs/locale/test/locale_test.cpp libs/decimal/src/decimal64.cpp

There are some differences in streaming which causes a few test errors for
- VC70 only inserts spaces in the money format if the "internal" adjustment
flag and width is set. g++ always inserts 1 space when specifed in the format.
I assumed g++ was right so VC70 fails this test.
- The default locale with g++ seem to miss a '-' sign for the money format so
it fails tests with negative numbers.

Library is available here
Documentation is available in the download as well.

Boost list run by bdawes at, gregod at, cpdaniel at, john at