Boost logo

Boost :

From: Daniel Frey (d.frey_at_[hidden])
Date: 2005-01-09 11:24:58


Martin wrote:
>>The point is that when I want to use a new underlying type for
>>calculations, I have a single point of customization, about 100-200
>>lines. The specialization of decimal_traits<T> for that type T and the
>>typedef for decimal. I don't have to touch the 300.000+ lines of code
>>that use it. What do you prefer?
>
>
> With your solution:
> 1. typedef basic_decimal<decimal64> decimal
> 2. typedef basic_decimal<decimalBCD> decimal
>
> With my solution
> 1. typedef decimal64 decimal;
> 2. typedef decimalBCD decimal;

No. I mean, yes, this works for two types, when both share the same
interface. But how can you be sure that RWDecimal<RWMP3Int> is
compatible with your decimal64?

typedef RWDecimal<RWMP3Int> decimal;

is unlikely to work for your project.

> Same amount of code to change. (We both need to implement the interface, you
> do it in decimal_traits, I do it in decimal64 & decimalBCD). What worries me
> with your solution is that your decimal_traits class implies a way to
> implement things that might not be the most efficient one for each
> implementation.

Your decimal64 is both an interface *and* an implementation. I just
suggest to separate it. Let basic_decimal take care of the interface,
while decimal64 takes care of the implementation.

> Lets take an example:
> Assume that basic_decimal implements "<=" as "traits::less_than ||
> traits::equal" which works fine if "less_than" and "equal" are "cheap"
> operations. In decimal64, both "less_than" & "equal" might need to scale one
> of the operands before the comparison so the scaling occurs twice in "<=".

That won't be a problem, as the decimal_traits class will implement the
operators. By default, every call to an operator should be forwarded
(inline) to the underlying type. No inefficiency involved, only freedom
for the user to overwrite operators when he wishes to.

> With my solution I am free to implement the interface in the most efficient
> way for each class.

Me too.

>>I think it's most useful if you work on decimal64 independently of
>>money/currency issues. Make it a cool new float-point type and
>>basic_decimal will be able to use it :)
>
> Do you have an example of an application where decimal floating point is
> useful? To me floating point means that you give up precision to be able to
> handle a large range of values. But if loss of precision is acceptable, you
> can just as well use binary floating point.

Maybe I don't understand the question, but I think it should be obvious
that a decimal based float point types has a lot of advantages. It's not
free of any rounding issues, but the problems are more intuitive. Most
people don't have a problem to accept rounding in general, it's just
examples like

double d = 0;
for( int i=0; i<100; ++i ) d += .01;
if( d == 1 ) { ... }

that are a source of so many problems.

>>Another benefit of the indirection through basic_decimal<T>: FWIW, there
>>is one thing that my classes don't do right now and which I always
>>dreamed of: "Correct" epsilon handling. Like
>>
>>operator== respects a given epsilon
>>native_less(a,b) like the current operator< for the underlying type
>
>
> Isn't the whole point with decimal math that values are stored exactly? Why
> would you need epsilon for exact values?

If you really try to store the values exactly, consider:

decimal64 d = 1;
d /= 3;
d *= 3;
if( d == 1 ) { ... }

will this work for your type? How?

Regards, Daniel


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