|
Boost : |
From: John Max Skaller (skaller_at_[hidden])
Date: 2001-05-10 17:44:49
Bill Seymour wrote:
> One discussion I'd like to have is about the type of the
> result of arithmetic operations.
Yes, you got them wrong. Here is the correct
typing:
1. increment and decrement are undefined
2. The arguments of a multiplication can be any scale n and m,
the result has scale n+m
3. Operator*= requires the argument to have scale 0
4. Quotient. The argument have the same scale,
the result has scale 0
5. operator/= is undefined
All other operations have the result and arguments of the same
scale. Including % and %=.
All the mathematical operations are radix independent:
they're correct for any radix, not just 10.
All the operations can be implemented with the corresponding
operations on the representation.
The conversion from another scale should be 'explicit'.
This operation is EXPENSIVE, and it is very VERY dangerous.
The conversion from 'char *' needs notes on error handling
and what is expected. Do the number of digits have to be correct?
There should be a conversion from string.
OPINION: All the non-assignment operations should be functions,
NOT members. NEVER use members for functional operations.
OPINION: All arguments (except the copy ctor) should use pass by value.
Its much faster to pass an 'int' than to pass a pointer.
However, this may vary from compiler to compiler.
And consistency with other interfaces may be important.
OPINION: REMOVE the money class. This should be proposed separately,
and the discussion should be separate.
OPINION: REMOVE the constructor taking the integral and fractional
parts.
It just confuses things. It may be useful to add it back later.
OPINION: Provide a default constructor, which guarrantees initial value
0.
-----------------------------------------------------------------
For your interest, here is a fixed_base type which could be
derived from to provide basic mathematics. It could be
extended to include a 'radix' argument for extra safety,
but I elided that for pedagogical reasons. The file
is NOT a proposal!
-----------------------------------------------------------------
// FIXED POINT TYPES modeled by a type INT
// PHILOSOPHY
//
// This class allows any integral type,
// or class emulating one, to be used as a fixed
// point integer using the native operations
// on that type.
//
// Only operations which can be directly inlined
// and are radix independent are supported.
//
// In other words, the whole of this file
// consists of typing information, and nothing more.
// There are NO algorithms of any kind here.
//
// The results will only be correct if the implied
// radix for each value is the same. This is not checked.
//
// NOTES
//
// 1. All operations use pass by value
//
// 2. Increment and decrement cannot be implemented
// because the radix is unknown
//
// 3. Any two fixed point values using the same representation,
// and the same implied radix can be multiplied,
// the result has n+m digits after the point,
// where n and m are the number of digits after the point
// in each of the arguments
//
// 4. It follows *= must have n=0
//
// 5. The arguments of a division must have the same scale.
// The quotient is always scaled n=0
// The remained has the same scale as the arguments,
// since it is what is left over after repeated subtraction
template<class INT, int n> // n is number of places after point
struct fixed_base
{
INT v; // public to avoid a whole lot of friend declarations
fixed_base(INT i) : v(i) {}
fixed_base<INT,n> operator += (fixed_base i) { v+=i.v; }
fixed_base<INT,n> operator -= (fixed_base i) { v+=i.v; }
fixed_base<INT,n> operator *= (fixed_base<INT,0> i) { v+=i.v; }
fixed_base<INT,n> operator %= (fixed_base<INT,0> i) { v/=i.v; }
};
// UNARY OPERATIONS
// absolute value
template<class INT, int n>
fixed_base<INT,n> abs
(
fixed_base<INT,n> i
)
{ return abs(i.v); }
// unary + (nop)
template<class INT, int n>
fixed_base<INT,n> operator +
(
fixed_base<INT,n> i
)
{ return -i.v; }
// negate
template<class INT, int n>
fixed_base<INT,n> operator -
(
fixed_base<INT,n> i
)
{ return -i.v; }
// BINARY OPERATIONS
// addition
template<class INT, int n>
fixed_base<INT,n> operator +
(
fixed_base<INT,n> i,
fixed_base<INT,n> j
)
{ return i.v + j.v; }
// subtraction
template<class INT, int n>
fixed_base<INT,n> operator -
(
fixed_base<INT,n> i,
fixed_base<INT,n> j
)
{ return i.v - j.v; }
// multiplication
template<class INT, int n, int m>
fixed_base<INT,n+m> operator *
(
fixed_base<INT,n> i,
fixed_base<INT,m> j
)
{ return i.v * j.v; }
// quotient
template<class INT, int n>
fixed_base<INT,0> operator *
(
fixed_base<INT,n> i,
fixed_base<INT,n> j
)
{ return i.v / j.v; }
// remainder
template<class INT, int n>
fixed_base<INT,n> operator *
(
fixed_base<INT,n> i,
fixed_base<INT,n> j
)
{ return i.v % j.v; }
// equality
template<class INT, int n>
fixed_base<INT,n> operator ==
(
fixed_base<INT,n> i,
fixed_base<INT,n> j
)
{ return i.v == j.v; }
// inequality
template<class INT, int n>
fixed_base<INT,n> operator !=
(
fixed_base<INT,n> i,
fixed_base<INT,n> j
)
{ return i.v != j.v; }
// less
template<class INT, int n>
fixed_base<INT,n> operator <
(
fixed_base<INT,n> i,
fixed_base<INT,n> j
)
{ return i.v != j.v; }
// less equal
template<class INT, int n>
fixed_base<INT,n> operator <=
(
fixed_base<INT,n> i,
fixed_base<INT,n> j
)
{ return i.v <= j.v; }
// greater
template<class INT, int n>
fixed_base<INT,n> operator >
(
fixed_base<INT,n> i,
fixed_base<INT,n> j
)
{ return i.v > j.v; }
// greater equal
template<class INT, int n>
fixed_base<INT,n> operator >
(
fixed_base<INT,n> i,
fixed_base<INT,n> j
)
{ return i.v >= j.v; }
-- John (Max) Skaller, mailto:skaller_at_[hidden] 10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850 checkout Vyper http://Vyper.sourceforge.net download Interscript http://Interscript.sourceforge.net
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk