# ideas for a generalized unit-handling class

• 06-18-2008
m37h0d
ideas for a generalized unit-handling class
it would be wonderful if i could implement a generalized unit class, but as simple of a concept as it is, a good way to implement it eludes me...

here's what i have so far, obviously it's clumsy and woefully inadequate, but at least it's a starting point for some discussion.

Code:

```class unit {         public:         unit(size_t NumUnits) : numUnits(NumUnits){}         double exponent;         double coeff;         const  size_t numUnits;         unit *units;         double convert(unit u)         {                 //returns a conversion factor if this and u are of compatible dimensions         };         unit multiply(unit u)         {                 //adds exponents of this->units of this and u->units         }         unit divide(unit u)         {                 //subtracts exponents of this->units of and u->units         } };```
there has got to be a more elegant and robust way of doing this. any suggestions (including 3rd party wares) would be greatly appreciated.
• 06-19-2008
medievalelks
You're talking about units of measurement, I assume? First question is how would clients of the class use it? And are you talking about all units (length, volume, pressure, force, mass, etc.)?

A class hierarchy seems to wrong way to approach this. I'd start with a set of conversion functions.
• 06-19-2008
rudyman

Try something like this:

5dam + 100cm = 51m
Code:

```unit m = unit(5).deca_meters() + unit(100).centi_meters(); // m.meters() == 51```
• 06-19-2008
CornedBee
Boost's review queue contains two different candidates for unit libraries.
• 06-19-2008
m37h0d
Quote:

Originally Posted by rudyman

Try something like this:

5dam + 100cm = 51m
Code:

```unit m = unit(5).deca_meters() + unit(100).centi_meters(); // m.meters() == 51```

yes, that would be a good idea for unit prefixes d,m,c,k,etc; but otherwise, it is not particularly useful.

i'd have to create operators for hundreds of possible permutations of units.
• 06-19-2008
m37h0d
Quote:

Originally Posted by CornedBee
Boost's review queue contains two different candidates for unit libraries.

just dl'd 1_35.07z and it doesn't appear to have been released yet, tho they say they'd added it. :\
• 06-19-2008
m37h0d
so, what i see as the major weakness in the above class is the sorting of the array unit::units

in order to check dimensional compatibility or perform an operation i would have to loop over the entire array numUnits times.

Probably not too expensive, but it is a rather ugly brute force implementation...
• 06-19-2008
matsp
Quote:

Originally Posted by m37h0d
so, what i see as the major weakness in the above class is the sorting of the array unit::units

in order to check dimensional compatibility or perform an operation i would have to loop over the entire array numUnits times.

Probably not too expensive, but it is a rather ugly brute force implementation...

Instead of having conversions between each type of unit, have a "standard unit" for each type of unit (so distances are perhaps in meter, time in seconds, energy in Joule, etc).

That way, you just need a table for each type of unit.

To make for example speed units, then you would have a "multi_unit class", which links for example a distance unit to a time unit to produce speed (base-unit is meters per second, but you can use the conversions to make this into miles per hour (meter-> miles, seconds->hours) or inches/s, etc). This would also apply to "area" and "volume", where you would combine two or three lengths into a multi_unit.

You'd obviously need to know if the multi-unit is multiplicative or divisive or perhaps even a combination of, e.g. liters of fuel per kilometer is obliviously a volume divided by distance [whcih can be simplified to an area measurement, but that doesn't actually make any sense whatsoever] - this would then translate to Miles per gallon, which is an distance / volume.

--
Mats
• 06-19-2008
m37h0d
yes, i use "kms" units as my algorithmic standard. having an internal standard like that is required to do a conversion at all; otherwise how do you know how many miles are in a parsec, for example.

i often need to change the way that the quantities are displayed; e.g. displaying 1ppm instead of 0.0001 wt&#37;.

also, our customers in europe aren't particularly fond of "psi", whereas our U.S. customers are quite happy with that and might not be familiar with kPa.

it would also be useful for my purposes in my calculations for checking or preventing unit-conversion errors.

anyway, if i'm interpreting you correctly here, you're suggesting that i make a few derived classes of unit to represent the principal quantities: e.g. mass, length, time, temperature, etc.; then create a multi-unit container class that handles the conversion.

i had considered something like this, but i am at a loss for an efficient way to perform the operations and dimensional consistency checking...
• 06-19-2008
CornedBee
Quote:

Originally Posted by m37h0d
just dl'd 1_35.07z and it doesn't appear to have been released yet, tho they say they'd added it. :\

True. It's in the SVN trunk, though, so it'll be in 1.36.0.
• 06-19-2008
matsp
Yes, one base-unit that you derive length/distance, mass, etc from.

Also, for most intents and purposes 1mg/L is also 1ppm (although that's only valid for water, and to be very precise, only at 4 degrees Celsius).

Which makes me realizse that temperatures (and possibly other conversions) may need an offset to convert from one to another - C to F definitely does. I think there are variants of pressure using the unit bar that are either "zero- or one-based", meaning that a total vacuum is either -1 or 0 depending on which variant of bar you use. Just to make sure you don't just use a multiplicative conversion.

I'm sorry, but I can't (quickly) come up with a neat solution as to the best way to do conversions between units and check correctness - I suppose if you take any unit back to it's base-units, you'd be able to verify that the two base-units are the same.

--
Mats