ConUom 1.1.0
dotnet add package ConUom --version 1.1.0
NuGet\Install-Package ConUom -Version 1.1.0
<PackageReference Include="ConUom" Version="1.1.0" />
paket add ConUom --version 1.1.0
#r "nuget: ConUom, 1.1.0"
// Install ConUom as a Cake Addin #addin nuget:?package=ConUom&version=1.1.0 // Install ConUom as a Cake Tool #tool nuget:?package=ConUom&version=1.1.0
ConUom
ConUom is a .NET Core library that allows you to define units of measure and then convert between them in C# or F#.
C# example
Let's start by defining the meter as a base unit of length:
var m = new Unit("Length", "m");
We can then derive new units in terms of existing units. For example, a centimeter is 1/100<sup>th</sup> of a meter:
var cm = 0.01m * m;
Note that the m
at the end of 0.01m
indicates a fixed-point decimal literal (rather than floating-point). We use exact values to avoid rounding errors.
We can convert from metric to U.S. units by defining the inch as exactly 2.54 centimeters:
var inch = 2.54m * cm;
Of course, a foot is then 12 inches, and a yard is 3 feet. We can even define a square yard via the ^
operator:
var ft = 12 * inch;
var yd = 3 * ft;
var sqyd = yd ^ 2;
Note that all of the above values are of type Unit
, and they're all based on the Length dimension we defined at the top. Now let's measure out exactly 8 square yards:
var areaSqYd = sqyd.Measure(8);
This value has type Measurement
. How many square meters are in 8 square yards? We can find out by converting units:
var areaSqM = areaSqYd.ConvertTo(m ^ 2);
Console.WriteLine($"{areaSqYd.Value} square yards = {(double)areaSqM.Value} square meters");
// Output: 8 square yards = 6.68901888 square meters
Using standard units
Instead of defining our own units from scratch, we can download a large collection of standardized units maintained by Frink:
using var client = new WebClient();
var str = client.DownloadString("https://frinklang.org/frinkdata/units.txt");
var success = Frink.TryParse(str, out UnitLookup lookup);
Assert.IsTrue(success);
For example, MIT's favorite unit of length is the "smoot". We can use Frink's definition like this:
var smoot = lookup["smoot"];
The school's radio station, WMBR, broadcasts at a frequency of 88.1 MHz:
var wmbr = lookup["megahertz"].Measure(88.1m);
We can convert this frequency to a wavelength using the speed of light:
var c = lookup["c"].Measure(1);
var wavelength = c / wmbr;
So, how long is WMBR's wavelength in smoots? That's easy to calculate:
var nSmoots = wavelength.ConvertTo(smoot);
Console.WriteLine((double)nSmoots.Value);
// Output: 1.999568447856973
Almost exactly 2!
F# example
ConUom is written in F# and there are several benefits to using its F# API as well. To start with, we can parse the Frink data file, much like we did above in C#:
use client = new WebClient()
let lookup, msgOpt =
client.DownloadString("https://frinklang.org/frinkdata/units.txt")
|> Frink.parse
msgOpt |> Option.iter Assert.Fail
Note that this version of the parser returns an Option<string>
that contains an error message if the parse fails, in addition to the same UnitLookup
we saw earlier.
This lookup can then be accessed using F#'s dynamic ?
operator:
let km = lookup?km
let megaparsec = lookup?megaparsec
let s = lookup?s
let gigayear = lookup?gigayear // billions of years
Note that we can look up "gigayear" even though it is not explicitly defined in the Frink file, because "giga" is a known prefix (meaning 1 billion) and "year" is a known unit. Let's use these units to calculate the age of the universe, shall we? This can be done easily using the Hubble constant, which is the rate at which the universe is expanding. We'll assume a value for this constant of 73 km/s/megaparsec:
let hubble = 73 @ km/s/megaparsec
Here we've used the @
operator to create a measurement. The difference between @
and *
is subtle, but important:
let meas = 12 @ inch // a measurement of 12 inches
let unit = 12 * inch // a unit of 12 inches (i.e. the foot)
The base units of the Hubble constant are 1/seconds (or s<sup>-1</sup>), and the reciprocal of the Hubble constant is the age of the universe in seconds. Since that's a very large number, we convert it to billions of years using the =>
operator:
let universe = 1/hubble => gigayear
printfn "%A" <| float universe.Value
// Output: 13.39470009
Thus, by this calculation, the universe is approximately 13.4 billion years old.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- FParsec (>= 1.1.1)
- FSharp.Core (>= 8.0.100)
- MathNet.Numerics (>= 5.0.0)
- MathNet.Numerics.FSharp (>= 5.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.