Skip to content

A closer look at unit representations

spatchcock edited this page Jan 19, 2012 · 7 revisions

Units in the Quantify gem are instances of the class Quantify::Unit::Base and its subclasses. This class defines 3 descriptors on each instance of a unit: the name, the symbol and the label. Names and symbols are the obvious conventional descriptors for each unit. Unit labels are unique references which follow the Java JScience library.

It should be noted that the three unit descriptors serve a dual purpose: they are used for both obtaining and representing unit objects. So, to get an instance of a known unit, use any of the descriptors like this:

unit = Unit.for("pound mole")            # a unit name
unit = Unit.K                            # a unit symbol
unit = Unit.ton_us                       # a label

or in the context of defining a quantity

quantity = Quantity.new(500,"hertz")     # using a unit name
quantity = 1000.km                       # using a unit symbol

Once you have a unit object, or a quantity object (which holds a unit object) you might want to use it in an operation or conversion but you will probably want to represent it or a by-product somehow. For quantities, there is a convenient #to_s method which prints out the quantity value and unit symbol by default:

quantity.to_s                            #=> "500.0 Hz"

This method also takes an argument for switching the unit representation:

quantity.to_s :name                      #=> "1000.0 kilometres"

Notice that this variant pluralizes the unit name. That is, unless the quantity value is exactly equal to 1 or -1. But what if we want more control over how we display our quantities? In this case we can handle the quantity value and units separately, delegating the unit representation to the properties of the unit object.

quantity.value                           #=> 1000.0
quantity.unit.name                       #=> "kilometre"
quantity.unit.pluralized_name            #=> "kilometres"
quantity.unit.label                      #=> "kg"
quantity.unit.symbol                     #=> "kg"

Okay, so that was easy. There are a few more things to consider when when dealing with compound units though. Compound units are those units which are the result of operating on (multiplying, dividing, raising to powers) one or more units. For example:

compound = Unit.mile / Unit.hour
compound.name                            #=> "mile per hour"
compound.pluralized_name                 #=> "miles per hour"
compound.symbol                          #=> "mi/h"
compound.label                           #=> "mi/h"

compound  = Unit.t * Unit.km
compound.name                            #=> "tonne kilometre"
compound.pluralized_name                 #=> "tonne kilometres"
compound.label                           #=> "t km"
compound.label                           #=> "t·km"

compound = Unit.m ** 2
compound.name                            #=> "square metre"
compound.pluralized_name                 #=> "square metres"
compound.symbol                          #=> "m²"
compound.label                           #=> "m²"

Again. notice that the #pluralized_name method intelligently chooses the appropriate base unit to pluralize, so that a complex quantity operation ends up with a readable string like this:

q = (2.kg * (5.m * 1.m)) / 2.s
q.to_s                                   #=> "5.0 kg m²/s"
q.to_s :name                             #=> "5.0 kilogram square metres per second"

Quantify allows a bit more control over how compound units are represented though. Note that the following are all global switches and will affect all units.

The unit delimiter. The ‘unit delimiter’ is basically the character that separates units in the compound unit representation. By default a space is used for unit names and unit symbols, whereas unit labels use the middot character. For symbols, this can be overridden globally to any character:

(Unit.kg / (Unit.t * Unit.km)).symbol    #=> "kg/t km"
Unit.symbol_unit_delimiter = "·"
(Unit.kg / (Unit.t * Unit.km)).symbol    #=> "kg/t·km"

The denominator delimiter. This is the character which separates numerator and denominator unit. Again, names and labels are prescribed - using “per” and "/" respectively - but symbols can be configured:

(Unit.km / Unit.h).symbol                #=> "km/h"
Unit.symbol_denominator_delimiter = " / " # extra whitespace
(Unit.km / Unit.h).symbol                #=> "km / h"
Unit.symbol_denominator_delimiter = " per "
(Unit.km / Unit.h).symbol                #=> "km per h"

Parentheses. If multiple units occur within the numerator or denominator, these can be grouped by parentheses in unit symbols:

(Unit.kg / (Unit.t * Unit.km)).symbol    #=> "kg/t km"
Unit.use_symbol_parentheses = true
(Unit.kg / (Unit.t * Unit.km)).symbol    #=> "kg/(t km)"

Denominator syntax or negative indices. Sometimes we might not want to separate unit into numerator and denominator units anyway in which case we need to use negative indices:

(Unit.km / Unit.h).symbol                 #=> "km/h"
Unit.use_symbol_denominator_syntax?       #=> true
Unit.use_symbol_denominator_syntax = false
Unit.use_symbol_denominator_syntax?       #=> false
(Unit.km / Unit.h).symbol                 #=> "km h^-1"

Superscript characters. By default, Quantify uses superscript characters for representing indices of 1,2 or 3. This can be overridden if "^" syntax is universally preferred:

(Unit.m**3).symbol                        #=> "m³"
Unit.use_superscript_characters?          #=> true
Unit.use_superscript_characters = false
Unit.use_superscript_characters?          #=> false
(Unit.m**3).symbol                        #=> "m^3"