2023-07-10 17:56:05 +02:00
|
|
|
# Dimensionless Quantities
|
|
|
|
|
|
|
|
|
|
The quantities we discussed so far always had some specific type and physical dimension.
|
|
|
|
|
However, this is not always the case. While performing various computations, we sometimes end up with
|
2023-12-26 11:07:21 +01:00
|
|
|
so-called "dimensionless" quantities, which ISO defines as
|
2023-08-03 21:23:34 +02:00
|
|
|
[quantities of dimension one](../../appendix/glossary.md#dimensionless-quantity):
|
2023-07-10 17:56:05 +02:00
|
|
|
|
|
|
|
|
!!! quote "ISO/IEC Guide 99"
|
|
|
|
|
|
|
|
|
|
- Quantity for which all the exponents of the factors corresponding to the base quantities in
|
|
|
|
|
its quantity dimension are zero.
|
|
|
|
|
- The measurement units and values of quantities of dimension one are numbers, but such quantities
|
|
|
|
|
convey more information than a number.
|
|
|
|
|
- Some quantities of dimension one are defined as the ratios of two quantities of the same kind.
|
|
|
|
|
- Numbers of entities are quantities of dimension one.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Dividing two quantities of the same kind
|
|
|
|
|
|
|
|
|
|
Dividing two quantities of the same kind always results in a
|
2023-08-03 21:23:34 +02:00
|
|
|
[quantity of dimension one](../../appendix/glossary.md#dimensionless-quantity).
|
2023-07-10 17:56:05 +02:00
|
|
|
However, depending on what type of quantities we divide or what their units are, we may end up
|
|
|
|
|
with slightly different results.
|
|
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
In **mp-units**, dividing two quantities of the same dimension always results in a quantity
|
|
|
|
|
with the dimension being `dimension_one`. This is often different for other physical units
|
|
|
|
|
libraries, which may return a raw representation type for such cases. A raw value is also always
|
|
|
|
|
returned from the division of two `std::chrono::duration` objects.
|
|
|
|
|
|
|
|
|
|
To read more about the reasoning for this design decision, please check our
|
2023-08-03 21:23:34 +02:00
|
|
|
[FAQ](../../getting_started/faq.md#why-a-dimensionless-quantity-is-not-just-a-fundamental-arithmetic-type).
|
2023-07-10 17:56:05 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
### Dividing quantities of the same type
|
|
|
|
|
|
|
|
|
|
First, let's analyze what happens if we divide two quantities of the same type:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
constexpr QuantityOf<dimensionless> auto q = isq::height(200 * m) / isq::height(50 * m);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
In such a case, we end up with a dimensionless quantity that has the following properties:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
static_assert(q.quantity_spec == dimensionless);
|
|
|
|
|
static_assert(q.dimension == dimension_one);
|
|
|
|
|
static_assert(q.unit == one);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
In case we would like to print its value, we would see a raw value of `4` in the output with no unit
|
|
|
|
|
being printed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Dividing quantities of different types
|
|
|
|
|
|
|
|
|
|
Now let's see what happens if we divide quantities of the same dimension and unit but which have
|
|
|
|
|
different quantity types:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
constexpr QuantityOf<dimensionless> auto q = isq::work(200 * J) / isq::heat(50 * J);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Again we end up with `dimension_one` and `one`, but this time:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
static_assert(q.quantity_spec == isq::work / isq::heat);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
As shown above, the result is not of a `dimensionless` type anymore. Instead, we get a quantity type
|
2023-08-03 21:23:34 +02:00
|
|
|
derived from the performed [quantity equation](../../appendix/glossary.md#quantity-equation).
|
2023-12-26 11:07:21 +01:00
|
|
|
According to the [ISQ](../../appendix/glossary.md#isq), _work_ divided by _heat_ is the recipe for
|
|
|
|
|
the _thermodynamic efficiency_ quantity, thus:
|
2023-07-10 17:56:05 +02:00
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
static_assert(implicitly_convertible(q.quantity_spec, isq::efficiency_thermodynamics));
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
The quantity of `isq::efficiency_thermodynamics` is of a kind `dimensionless`, so it is implicitly
|
|
|
|
|
convertible to `dimensionless` and satisfies the `QuantityOf<dimensionless>` concept.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Dividing quantities of different units
|
|
|
|
|
|
|
|
|
|
Now, let's see what happens when we divide two quantities of the same type but different units:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
constexpr QuantityOf<dimensionless> auto q = isq::height(4 * km) / isq::height(2 * m);
|
|
|
|
|
```
|
|
|
|
|
|
2023-12-26 11:07:21 +01:00
|
|
|
This time, we still get a quantity of the `dimensionless` type with a `dimension_one` as its dimension.
|
2023-07-10 17:56:05 +02:00
|
|
|
However, the resulting unit is not `one` anymore:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
static_assert(q.unit == mag_power<10, 3> * one);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
In case we would print the text output of this quantity, we would not see a raw value of `2000`,
|
|
|
|
|
but `2 km/m`.
|
|
|
|
|
|
2023-12-26 11:07:21 +01:00
|
|
|
First, it may look surprising, but this is consistent with dividing quantities
|
2023-07-10 17:56:05 +02:00
|
|
|
of different dimensions. For example, if we divide `4 * km / 2 * s`, we do not expect `km` to be
|
|
|
|
|
"expanded" to `m` before the division, right? We would expect the result of `2 km/s`, which is
|
|
|
|
|
exactly what we get when we divide quantities of the same kind.
|
|
|
|
|
|
|
|
|
|
This is a compelling feature that allows us to express huge or tiny ratios without the need
|
|
|
|
|
for big and expensive representation types. With this, we can easily define things like
|
2023-12-26 11:07:21 +01:00
|
|
|
a [_Hubble's constant_](https://en.wikipedia.org/wiki/Hubble%27s_law#Dimensionless_Hubble_constant)
|
2023-07-10 17:56:05 +02:00
|
|
|
that uses a unit that is proportional to the ratio of kilometers per megaparsecs, which are both
|
2023-12-26 11:07:21 +01:00
|
|
|
units of _length_:
|
2023-07-10 17:56:05 +02:00
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
inline constexpr struct hubble_constant :
|
2024-04-19 15:29:00 +01:00
|
|
|
named_unit<{u8"H₀", "H_0"}, mag_ratio<701, 10> * si::kilo<si::metre> / si::second / si::mega<parsec>> {} hubble_constant;
|
2023-07-10 17:56:05 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Counts of things
|
|
|
|
|
|
|
|
|
|
Another important use case for dimensionless quantities is to provide strong types for counts
|
|
|
|
|
of things. For example:
|
|
|
|
|
|
2023-12-26 11:07:21 +01:00
|
|
|
- ISO-80000-3 provides a _rotation_ quantity defined as the number of revolutions,
|
|
|
|
|
- IEC-80000-6 provides a _number of turns in a winding_ quantity,
|
|
|
|
|
- IEC-80000-13 provides a _Hamming distance_ quantity defined as the number of digit positions
|
2023-07-10 17:56:05 +02:00
|
|
|
in which the corresponding digits of two words of the same length are different.
|
|
|
|
|
|
2023-12-26 11:07:21 +01:00
|
|
|
Thanks to assigning strong names to such quantities, later on, they can be explicitly used as
|
2023-08-03 21:23:34 +02:00
|
|
|
arguments in the [quantity equations](../../appendix/glossary.md#quantity-equation) of other
|
2023-07-10 17:56:05 +02:00
|
|
|
quantities deriving from them.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Predefined units of the dimensionless quantity
|
|
|
|
|
|
|
|
|
|
As we observed above, the most common unit for dimensionless quantities is `one`. It has the
|
|
|
|
|
ratio of `1` and does not output any textual symbol.
|
|
|
|
|
|
2023-10-25 14:14:26 +02:00
|
|
|
!!! important "Important: `one` is an identity"
|
2023-07-10 17:56:05 +02:00
|
|
|
|
|
|
|
|
A unit `one` is special in the entire type system of units as it is considered to be
|
2023-08-03 21:23:34 +02:00
|
|
|
[an identity operand in the unit expression templates](interface_introduction.md#identities).
|
2023-07-10 17:56:05 +02:00
|
|
|
This means that, for example:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
static_assert(one * one == one);
|
|
|
|
|
static_assert(one * si::metre == si::metre);
|
|
|
|
|
static_assert(si::metre / si::metre == one);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The same is also true for `dimension_one` and `dimensionless` in the domains of dimensions
|
|
|
|
|
and quantity specifications.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Besides the unit `one`, there are a few other scaled units predefined in the library for usage
|
|
|
|
|
with dimensionless quantities:
|
|
|
|
|
|
|
|
|
|
```cpp
|
2024-04-19 15:29:00 +01:00
|
|
|
inline constexpr struct percent : named_unit<"%", mag_ratio<1, 100> * one> {} percent;
|
|
|
|
|
inline constexpr struct per_mille : named_unit<{u8"‰", "%o"}, mag_ratio<1, 1000> * one> {} per_mille;
|
|
|
|
|
inline constexpr struct parts_per_million : named_unit<"ppm", mag_ratio<1, 1'000'000> * one> {} parts_per_million;
|
2024-01-20 00:05:54 +00:00
|
|
|
inline constexpr auto ppm = parts_per_million;
|
2023-07-10 17:56:05 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Angular quantities
|
|
|
|
|
|
2023-12-26 11:07:21 +01:00
|
|
|
Special, often controversial, examples of dimensionless quantities are an _angular measure_
|
|
|
|
|
and _solid angular measure_ quantities that are defined in the [ISQ](../../appendix/glossary.md#isq)
|
|
|
|
|
to be the result of a division of $arc\; length / radius$ and $area / radius^2$ respectively.
|
2023-08-03 21:23:34 +02:00
|
|
|
Moreover, [ISQ](../../appendix/glossary.md#isq) also explicitly states that both can be
|
2023-12-26 11:07:21 +01:00
|
|
|
expressed in the unit `one`. This means that both _angular measure_ and _solid angular measure_
|
|
|
|
|
should be of a [kind](../../appendix/glossary.md#kind) dimensionless.
|
2023-07-10 17:56:05 +02:00
|
|
|
|
2023-12-26 11:07:21 +01:00
|
|
|
On the other hand, [ISQ](../../appendix/glossary.md#isq) also specifies that a unit radian can
|
|
|
|
|
be used for _angular measure_, and a unit steradian can be used for _solid angular measure_.
|
2023-07-10 17:56:05 +02:00
|
|
|
Those should not be mixed or used to express other types of dimensionless quantities. This means
|
2023-12-26 11:07:21 +01:00
|
|
|
that both _angular measure_ and _solid angular measure_ should also be
|
2023-08-03 21:23:34 +02:00
|
|
|
[quantity kinds](../../appendix/glossary.md#kind) by themselves.
|
2023-07-10 17:56:05 +02:00
|
|
|
|
|
|
|
|
!!! note
|
|
|
|
|
|
|
|
|
|
Many people claim that angle being a dimensionless quantity is a bad idea. There are
|
|
|
|
|
proposals submitted to make an angle a base quantity and `rad` to become a base unit. More on this
|
2023-08-03 21:23:34 +02:00
|
|
|
topic can be found in the ["Strong Angular System" chapter](../defining_systems/strong_angular_system.md).
|
2023-07-10 17:56:05 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
## Nested quantity kinds
|
|
|
|
|
|
2023-12-26 11:07:21 +01:00
|
|
|
Angular quantities are not the only ones with such a "strange" behavior. Another but a similar case
|
|
|
|
|
is a _storage capacity_ quantity specified in IEC-80000-13 that again allows expressing it in both
|
2023-07-10 17:56:05 +02:00
|
|
|
`one` and `bit` units.
|
|
|
|
|
|
|
|
|
|
Those cases make dimensionless quantities an exceptional tree in the library. This is the only
|
2023-08-03 21:23:34 +02:00
|
|
|
[quantity hierarchy](../../appendix/glossary.md#quantity-hierarchy) that contains more than one
|
|
|
|
|
[quantity kind](../../appendix/glossary.md#kind) in its tree:
|
2023-07-10 17:56:05 +02:00
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart TD
|
|
|
|
|
dimensionless["dimensionless\n[one]"]
|
|
|
|
|
dimensionless --- rotation
|
|
|
|
|
dimensionless --- efficiency
|
|
|
|
|
dimensionless --- angular_measure["angular_measure\n[rad]"]
|
|
|
|
|
angular_measure --- rotational_displacement
|
|
|
|
|
angular_measure --- phase_angle
|
|
|
|
|
dimensionless --- solid_angular_measure["solid_angular_measure\n[sr]"]
|
|
|
|
|
dimensionless --- drag_factor
|
|
|
|
|
dimensionless --- storage_capacity["storage_capacity\n[bit]"] --- equivalent_binary_storage_capacity
|
|
|
|
|
dimensionless --- ...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
To provide such support in the library, we provided an `is_kind` specifier that can be appended
|
|
|
|
|
to the quantity specification:
|
|
|
|
|
|
|
|
|
|
=== "C++23"
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
inline constexpr struct angular_measure : quantity_spec<dimensionless, arc_length / radius, is_kind> {} angular_measure;
|
|
|
|
|
inline constexpr struct solid_angular_measure : quantity_spec<dimensionless, area / pow<2>(radius), is_kind> {} solid_angular_measure;
|
|
|
|
|
inline constexpr struct storage_capacity : quantity_spec<dimensionless, is_kind> {} storage_capacity;
|
|
|
|
|
```
|
|
|
|
|
|
2023-07-11 17:22:32 +02:00
|
|
|
=== "C++20"
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
inline constexpr struct angular_measure : quantity_spec<angular_measure, dimensionless, arc_length / radius, is_kind> {} angular_measure;
|
|
|
|
|
inline constexpr struct solid_angular_measure : quantity_spec<solid_angular_measure, dimensionless, area / pow<2>(radius), is_kind> {} solid_angular_measure;
|
|
|
|
|
inline constexpr struct storage_capacity : quantity_spec<storage_capacity, dimensionless, is_kind> {} storage_capacity;
|
|
|
|
|
```
|
|
|
|
|
|
2023-07-10 17:56:05 +02:00
|
|
|
=== "Portable"
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
QUANTITY_SPEC(angular_measure, dimensionless, arc_length / radius, is_kind);
|
|
|
|
|
QUANTITY_SPEC(solid_angular_measure, dimensionless, area / pow<2>(radius), is_kind);
|
|
|
|
|
QUANTITY_SPEC(storage_capacity, dimensionless, is_kind);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
With the above, we can constrain `radian`, `steradian`, and `bit` to be allowed for usage with
|
|
|
|
|
specific quantity kinds only:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
inline constexpr struct radian : named_unit<"rad", metre / metre, kind_of<isq::angular_measure>> {} radian;
|
|
|
|
|
inline constexpr struct steradian : named_unit<"sr", square(metre) / square(metre), kind_of<isq::solid_angular_measure>> {} steradian;
|
|
|
|
|
inline constexpr struct bit : named_unit<"bit", one, kind_of<storage_capacity>> {} bit;
|
|
|
|
|
```
|
|
|
|
|
|
2023-12-26 11:07:21 +01:00
|
|
|
but still allow the usage of `one` and its scaled versions for such quantities.
|