Skip to content

Instantly share code, notes, and snippets.

@markusjohnsson
Created November 30, 2021 07:16
Show Gist options
  • Save markusjohnsson/b4b65a9152e048a12238b130ea393aac to your computer and use it in GitHub Desktop.
Save markusjohnsson/b4b65a9152e048a12238b130ea393aac to your computer and use it in GitHub Desktop.
Units of measure in C#
using System;
class Unit
{
public string Name {get; private set;}
protected Unit(string name)
{
Name = name;
}
public static readonly Unit DimensionLess = new Unit(" ");
public static readonly Unit Meters = new Unit("meters");
public static readonly Unit Seconds = new Unit("seconds");
public static Unit operator / (Unit a, Unit b)
{
if (a.Name == b.Name) return DimensionLess;
return new FractionUnit(a, b);
}
public static Unit operator * (Unit a, Unit b)
{
if (a == DimensionLess) return b;
if (b == DimensionLess) return a;
var aFrac = a as FractionUnit;
if (aFrac != null && b == aFrac.Under)
return aFrac.Over;
var bFrac = b as FractionUnit;
if (bFrac != null && a == bFrac.Under)
return bFrac.Over;
return new MultUnit(a, b);
}
public static Scalar operator * (double a, Unit b)
{
return new Scalar(a, b);
}
}
class MultUnit : Unit
{
public Unit A {get; private set;}
public Unit B {get; private set;}
public MultUnit(Unit a, Unit b): base(a.Name + "*" + b.Name)
{
A = a;
B = b;
}
}
class FractionUnit : Unit
{
public Unit Over {get; private set;}
public Unit Under {get; private set;}
public FractionUnit(Unit over, Unit under): base(over.Name + "/" + under.Name)
{
Over = over;
Under = under;
}
}
class Scalar
{
public double Value { get;private set;}
public Unit Unit {get; private set;}
public Scalar(double v, Unit u)
{
Value = v;
Unit = u;
}
public static Scalar operator + (Scalar a, Scalar b)
{
if (a.Unit != b.Unit)
{
throw new InvalidOperationException(string.Format("cannot add scalars with units {0} and {1}", a.Unit.Name, b.Unit.Name));
}
return new Scalar(a.Value + b.Value, a.Unit);
}
public static Scalar operator - (Scalar a, Scalar b)
{
if (a.Unit != b.Unit)
{
throw new InvalidOperationException(string.Format("cannot subtract scalars with units {0} and {1}", a.Unit.Name, b.Unit.Name));
}
return new Scalar(a.Value - b.Value, a.Unit);
}
public static Scalar operator / (Scalar a, Scalar b)
{
return new Scalar(a.Value / b.Value, a.Unit / b.Unit);
}
public static Scalar operator * (Scalar a, Scalar b)
{
return new Scalar(a.Value * b.Value, a.Unit * b.Unit);
}
public static Scalar operator * (double a, Scalar b)
{
return new Scalar(a * b.Value, b.Unit);
}
public static Scalar operator * (Scalar a, double b)
{
return new Scalar(a.Value * b, a.Unit);
}
public override string ToString()
{
return string.Format("{0} {1}", Value, Unit.Name);
}
}
public class Program
{
public static void Main()
{
var distance = new Scalar(100, Unit.Meters);
var time = new Scalar(4, Unit.Seconds);
Console.WriteLine(distance / time);
Console.WriteLine((9.8 * (Unit.Meters/Unit.Seconds)) * (10 * Unit.Seconds));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment