Arithmetic Operations¶
Quantity arithmetic operations fall into two categories.
-
Arbitrary-unit operations work with any units — even if there are multiple input units with different dimensions! Examples include products, quotients, powers, and roots.
-
Common-unit operations require the inputs to be expressed in the same unit.1 Examples include addition, subtraction, and relational operators.
We’ll explain how the library handles each category below. First, a brief refresher.
Quantities, values, and units 101¶
A quantity is an abstract concept: some physical property that can be measured. To work with that quantity, we need to pick a unit of measure, or “unit”. Once we’ve done so, the quantity obtains a value with respect to that unit.
Different choices of unit will lead to different values for the same quantity. For example, suppose
we have a rod that is one foot long. The distance between its endpoints is feet(1.0)
, where
feet
is the unit, and 1.0
is the value. It’s also equal to inches(12.0)
, where inches
is
another unit we could have chosen, and 12.0
is the value we’d obtain if we did.
Note that feet(1.0)
and inches(12.0)
are the same quantity, conceptually! But when we pick
different units, we’ll end up storing different values (i.e., 1.0
vs. 12.0
) in the bits and
bytes of our computer program.
Arbitrary-unit operations¶
For arbitrary-unit operations (products, quotients, powers, and roots), there is a simple, golden rule: apply the operation (say, multiplication) independently to both the value and the unit. Consider this example:
Notice how the operation applies independently to the value and the unit:
- values: 150 \div 2 = 75
- units: \text{mi} \div \text{h} = \text{mi} / \text{h}
Au works the same way. Here’s how that computation would look in our library:
Here, (miles / hour)
creates a new, compound unit on the fly, and calling it on 75.0
stores
that value to create a quantity.
Mixed Units and Conversions¶
Au makes it easy to do complicated, multi-step operations. For example:
How many “g’s” of acceleration will a car experience, going from 0 to 60 MPH in 3 seconds?
Assuming constant acceleration, we have:
It’s worth breaking down the operations the library performs, and the order in which it performs them. In particular, remember that division happens first, before the assignment.
For the division, we know we can reason independently about the value; so, the value is 20.0
.
Similarly, the unit is miles / hour / second
. Altogether, the division step yields
20 \,\,\text{MPH} / \text{s}.
Next comes assignment. Since standard gravity (g_0) and \text{MPH}/\text{s} both have the same
dimension (namely, acceleration), then \frac{g_0}{\text{MPH}/\text{s}} is some real number:
namely, \frac{980665}{44704}. The library computes this number at compile time, and performs
only a single multiplication or division at runtime. The final printed result is roughly
0.911708 g_0
.
And this makes sense! We know intuitively that going from 0 to 60 MPH in 3 seconds “feels very fast”. We can see that in fact, it’s pulling almost a full “g”.
Common unit operations¶
If two quantities have the same dimension, it’s physically meaningful to add, subtract, or compare them. Consider two lengths: we can physically add them by placing them in series and measuring the total distance, even if we had measured one in “feet”, and the other in “inches”.
Computationally, it’s a different story: we need to express them in a common unit. Once we do, it’s easy to add/subtract/compare the quantities: we simply add/subtract/compare the values.
The “common unit” of two units is the largest unit that evenly divides both2—essentially, the greatest common divisor. This convention has two benefits:
-
Converting each input quantity to the common unit involves multiplying the value by an integer. This is really important for quantities with integral storage types!
-
The value of that multiplier will be as small as possible (relative to other units that evenly divide both input units). This minimizes the risk of integer overflow.
Let’s look at a few examples.
-
feet(1) + inches(6)
: This converts each input to their common unit, which isinches
, resulting ininches(18)
. -
inches(100) > centi(meters)(200)
: The common unit doesn’t have a name, so let’s call it \text{com}. An inch is 127 \,\text{com}, and a centimeter is 50 \,\text{com}. After implicitly converting each argument, the input reduces tocoms(12700) > coms(10000)
, which clearly evaluates totrue
.
Check your understanding: what would we get if we added these last values instead of comparing them?
We know that addition is a “common unit operation”, which means we have to convert both inputs
to the common unit before performing it. As above, let’s temporarily assume we’ve given a name,
coms
, to this anonymous unit. We already saw that these inputs convert to coms(12700)
and
coms(10000)
, respectively, so all we have to do is add them together to get coms(22700)
.
Of course, in real code, this unit wouldn’t have a name. We’d just have some Quantity
of an
anonymous length unit with this magnitude, storing the value 22700
. So: what can we do with
this result? Well, we can’t assign it to an integer Quantity of inches
or
centi(meters)
, because it’s not an integer in either of those units. However, we can…
- …compare it to an integer Quantity of
inches
orcenti(meters)
- …assign it to a floating point Quantity of
inches
orcenti(meters)
- …assign it to an integer Quantity of some smaller divisor unit, such as
micro(meters)
So, for example, this would work:
The value of x
would be micro(meters)(4'540'000)
.
-
Note that this is only possible in the first place if the units have the same dimension. ↩
-
Of course, this definition only applies to units which have a common divisor. This happens whenever their ratio (a dimensionless number) is an exact rational number. This won’t work for unit pairs such as
degrees
andradians
, whose ratio is the irrational number (\pi / 180). For “irrational ratios”, no convention can provide the benefits in this section, so we make an arbitrary choice based on convenience of implementation. For more details, see the common unit docs. ↩