|
Boost : |
From: Andy Little (andy_at_[hidden])
Date: 2003-11-06 00:03:04
Hi ,
In the previous debate about Physical Quantities,
An interesting question that came up was
What should the resulting units of a calculation between two different
types of units be?
I came to the conclusion that the best algorithm is the one that preserves
accuracy:
// "add_units_t" a metafunction to
// select the units giving best accuracy in addition...
// in addition both powers are the same
// but units can vary.
// here the most_granular units are selected if Power > 0
// the least granular if Power < 0
// if Power == 0 units are "dont care"
template<int Power,int UnitA,int UnitB>
struct add_units_t{
typedef typename boost::mpl::if_c
< Power,
typename boost::mpl::if_c
< ( Power > 0 ),
typename most_granular_units_t<UnitA,UnitB> ::type,
typename least_granular_units_t<UnitA,UnitB> ::type
> ::type,
unit_traits<0>
> ::type type;
};
// which gives the following output:
1001 mm
1001 mm
60001 mm.minutes-1
60001 mm.minutes-1
from the code below:
using namespace physical_quantities;
int main()
{
pq_length<double>::m L1(1.0L); //metres
pq_length<double>::mm L2(1.0L); //millimetres
std::cout << L1 + L2 <<'\n'; // ---> 1001 mm
std::cout << L2 + L1 <<'\n'; // ---> 1001 mm
pq_velocity<int>::mm_per_minute V1(1); //millimetres per minute
pq_velocity<int>::m_per_s V2(1); // metres per second
std::cout << V1 + V2 <<'\n';
//---> 60001 mm.minutes-1 .... Think about it
:-)
std::cout << V2 + V1 <<'\n';
//---> .60001 mm.minutes-1
return 0;
}
It may not be entirely intuitive but it is the best way to preserve accuracy
especially when using ints as in second example.
Well I better check it runs on Gcc and then hopefully I shall be able to put
what I
have up in the boost "backroom"
within the week
Andy Little
andy_at_[hidden]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk