Boost logo

Boost :

From: Martin (adrianm_at_[hidden])
Date: 2005-01-13 09:16:20


I think the discussion on the decimal went in the wrong direction and is it
probably my own fault. Lets start it over in more general terms.

My view on decimal types are that they can be based on 4 different base types
 
1. binary floating-point, explicit rounding
2. decimal floating-point, explicit rounding
3. decimal fixed-precision, global rounding
4. decimal fixed-precision, object rounding

* Explicit rounding means that all operations store the full precision
supported by the type. Rounding to a number of decimals is performed when
needed by a (maybe implicit) call to a function like round(x, rounding_mode).
Ofcourse there is a rounding mode used to fit the result of an operation into
the type which might cause rounding errors (e.g. 0.499999 might first be
rounded to 0.5000 to fit the type which is then explicitly rounded to 1). I
think the cases where the double rounding is a problem are so rare that it is
enough to point out the problem in the documentation.

* global rounding means the same rounding is used for all objects.
* object rounding means that the rounding is specified for each object.

The decimal type I proposed was in category 4. The proposed TR decimal type is
category 2 and it might also support type 3. Float, double is category 1.

---
The discussion on decimal types, including the review of a decimal library two 
years ago, indicates that to be accepted in boost a solution should allow some 
(or all 4) types to be used as base in something like "basic_decimal<>".
So lets discuss how a basic_decimal interface should look like. The main 
problem I see lies in the construction:
Type 1 & 2: basic_decimal(value)
Type 3:     basic_decimal(value, precision)
Type 4:     basic_decimal(value, precision, rounding_mode)
Rounding is not a big problem since a sensible default can be used but how to 
solve the precision? Creating a decimal type 3 or 4 without specifying a 
precision is bad since there is no good value to use as default. Precision 
also has a different meaning for a decimal type 1 & 2 (i.e. only affects 
extractions, not operations).
I see three possible solutions:
1. basic_decimal include all variants of constructors and then generates 
compiler error if that type of constructor isn't suitable for the underlying 
type
2. basic_decimal only got the "full" constructor (value, precision, 
rounding_mode) but supplies default for precision (=0?) and rounding mode
3. basic_decimal only includes the minimal constructor (value) and then other 
members are needed to specify precision and rounding_mode for type 3 & 4 
decimals.
The other members of basic_decimal isn't very complicated:
A full set of arithmetic operations (+,-,*,/,%) and assignment must be 
included. 
Operations should work on integers and maybe also string literals. For decimal 
type 1 & 2 it makes sense to also allow operations on doubles.
Assignment should work on integers, string literals and double for all types.
There needs to be a way to extract the decimal as a binary floating point 
value and probably also a decimal floating point value (when available). 
Functions like round, abs etc are also needed but they can be free functions 
(maybe friends for performace reasons).
Note that the above only deals with the decimal type. Money and currency might 
need a slightly different interface. My view is that the types should built up 
like:
typedef basic_decimal<value_type> decimal_type;
typedef basic_money<decimal_type> money_type;
typedef basic_currency<money_type> currency_type;
Any comments?

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