ConUom 1.1.0

dotnet add package ConUom --version 1.1.0
NuGet\Install-Package ConUom -Version 1.1.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ConUom" Version="1.1.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add ConUom --version 1.1.0
#r "nuget: ConUom, 1.1.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.1.0 161 12/28/2023
1.0.0 429 7/26/2020