Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / DevOps / unit-testing

UnitConversionLib: Smart Unit Conversion Library in C#

4.78/5 (8 votes)
23 Jun 2014CPOL6 min read 47.9K  
Information on how to use UnitConversionLib in C# for changing units and quantities

Introduction

This article is about UnitConversionLib, an open source library for conversion of units, arithmetic operation and parsing quantities with their units on run time. In this article, codes are provided in C#. you can download the library from Codeplex by going to this link. And clicking on the download button on the right side of the page.

Link and Download

UnitConversionLib is an Open Source library available at Codeplex:

For downloading it, go to the link above and click on the 'download' button (colored with violet) in the right side of page and you should receive the .dll file.

Background

I am a civil engineer and when I was a student, I was involved with many values and formulas, one in metric system and other one in other system! So several years ago, I tried to create a library in .NET which let the user to be able to consider the units of values easily and lets the machine do the heavy job.

The idea of creating the UnitConversionLib is:

  • Letting users to be able to use the Visual Studio (any version, including Express) environment and C# code for parsing and arithmetic operations between quantities.
  • Letting users to change and work with Units of Measurement in .NET in runtime.

As its coder, I do not guarantee the accuracy and validity of the library and the library like many other Opensource Libraries is 'AS IS'!

Next, I’m going to show you to how to use the library and a brief information about the library.

*Note: You may encounter some spelling errors in the library code at Codeplex, sorry for them!

Units of Measurement

There is a struct named UnitConversionLib.Unit which holds information about a unit of measurement. Basically there are two types of Units, ‘Base Units’ and ‘Derived Units’:

  • Base Units, are units that are not derived from any unit. For example, in SI there are 5 base units that all other units are derived from:
    • Meter
    • Kilogram
    • Second
    • Ampere
    • Kelvin
    • Mol
    • Candela
  • Derived Units, are units that are derived from base units, all units in SI except 5 base units are derived from the 5 base units. There are several examples:
    • N=kg·m/s2
    • Hz=1/s

*Note: Derived units are not implemented as derived classes in UnitConversionLib.

All SI base units (except Kelvin, check the Note in Consistent Units section) and some derived SI units are predefined in the library and you can check the list from the wiki page of UnitConversionLib on Codeplex.

Creating Base Units

Although the SI base units are pretty comprehensive, but sometimes there is a need for creating new base units. Unlike some other unit conversion libraries, the base units are not hard coded in UnitConversionLib and the user is able to create them on the fly! For example, we want to create a ‘Bit’ base unit:

C#
Unit bit = Unit.CreateNew("b");//Create a new fundamental unit

You have to pass the name of unit to Unit.CreateNew() method for identifying the name for library. This name will be used for parsing the Units from string.

Creating Derived Units

For example, we want to create a byte unit which is derived from bit:

C#
Unit B = bit * 8;

As you can see the ‘*’ and ‘/’ operators are overloaded for Unit class.

After creating the unit, you can register a name for it to be used in parsing units from string.

C#
Unit.Register(ref B, "B");

For example, we have registered the byte unit with uppercase ‘B’ and we will be able to parse this unit like either of these methods:

C#
Unit unt0 = Unit.GetRegisteredUnit("B");//method 1: From registered library
Unit unt1 = Unit.Parse("B");//method 2: Parsing from string - simple format
Unit unt2 = "B";//method 3: <a href="http://msdn.microsoft.com/en-us/library/z5z9kes2.aspx">Implicit conversion!

In this case unt0, unt1 and unt2 are equal. As equality operators (== and !=) are overloaded for Unit class, you can check the equality of units with == operator:

C#
Debug.Assert(unt0 == unt1 && unt1 == unt2 && unt2 == unt3);

We also will create ‘KB’ and ‘MB’ which are equals to 1024 B and 1024 KB.

C#
Unit KB = B * 1024;
Unit.Register(ref KB, "KB");
Unit MB = KB * 1024;
Unit.Register(ref MB, "MB");

Once we’ve registered new Units KB and MB, we will be able to use them. For example, creating units ‘bps’ (Bit Per Second), ‘Bps’ (Byte Per Second) and ‘KBps’ (KiloByte per second) is shown in several ways in the next snippet.

C#
var bps = Unit.Parse("b") / Unit.Parse("sec");//using .Parse() method
Unit.Register(ref bps, "bps");
var Bps = Unit.Parse("B/sec");// Parsing complex unit from string
Unit.Register(ref Bps, "Bps");
var KBps = "KB" / Unit.Parse("sec");//using implicit conversion from string to unit
Unit.Register(ref KBps, "KBps");

Consistent Units

There are units who are pointing to the same origin, best example is Gram and Kilogram that both are units of mass or N (Newton) and Kgf (Kilogram force) which are units of force. These types of Units are consistent and are convertible to each other with a constant coefficient, for example Kilogram=1000.0*Gram or 1Gram=0.001 Kg.

In UnitConversionLib, consistent units are convertible to each other and you can check it with Unit.IsConvertibleTo() method. If returned value is true, then units are convertible to each other with second double parameter which is specified with the out keyword (out keyword means that parameter value will set by method after executed). For example, snippet will check the consistency of Kilogram (Kg) and gram (gr) (while we know Gr*0.001=kg):

C#
Debug.Assert(Unit.Parse("kg").IsConvertibleTo("gm", out coefficient));
Debug.Assert(coefficient==0.001);

*Note: 'Kelvin' and 'Fahrenheit' and 'Celsius' cannot be converted to each other in UnitConversionLib because they are not consistent in UnitConversionLib as they are not a constant coefficients of each other (unlike, for example, Kg and Gr which 1000*Gr=Kg)

Measuring Quantities

Every measurable quantity consists of a Value (magnitude) and an Unit. UnitConversionLib.Measurable struct is used to represent a quantity that have both Unit and Magnitude. Like UnitConversionLib.Unit struct, several operators are overloaded for this Measurable objects, here is the list of operators and a brief information on each:

Arithmetic Operator Applicable Types Description
* Measurable*Measurable Multiplying two measurables
* Measurable*double Multiplying a measurable with a constant
^ Measurable^double Raising a measurable object to specified power
/ Measurable/Measurable Division of two measurables
/ Measurable/double Division of measurable with a double
/ double/Measurable Division of double with a measurable
+ Measurable+Measurable Addition of two measurable (Units of Two Measurable should be consistent)
== Measurable==Measurable Determining that are two measurable objects represents equal quantities
!= Measurable!=Measurable Determining that are two measurable objects represents equal quantities

This is an example of multiply and dividing Measurable objects, for example a car has gone through a 100 m distance in 10 second, the average speed of car will be 100 m / 10 sec = 10 m/sec:

C#
var D = Measurable.Parse("100 m");
var T = Measurable.Parse("10 sec");
var V = D/T;
Console.WriteLine("{0:0.0}",V); // will show 10.0 m/sec

Useful Code Snippets

In this snippet, several ways for parsing and working with units in UnitConversionLib exist:

C#
//Creating and parsing units
Unit unt0 = Unit.GetRegisteredUnit("N");//From registered library
Unit unt1 = Unit.Parse("N");//Parsing from string - simple format
Unit unt2 = "N";//Implicit conversion
Unit unt3 = Unit.Parse("kg*m/sec^2");//Parsing from string - from expression (1)
Unit unt4 = Unit.Parse("kg*m/s^(ton/kg/500)");//Parsing from string - from expression (2)
Unit unt5 = Unit.Parse("kg*m/s^(kg/kg*2)");//Parsing from string - from expression (3)
Unit unt6 = Unit.Parse("kg*m") / (Unit.Parse("sec") ^ 2);//Parsing from string - from expression (4)

Unit kg = Unit.Parse("kg");
Unit m = Unit.Parse("m");
Unit sec = Unit.Parse("sec");
Unit unt7 = kg * m / (sec ^ 2);//Evaluating through runtime

Debug.Assert(unt0 == unt1 && unt1 == unt2 && unt2 == unt3 && 
unt3 == unt4 && unt4 == unt5 && unt5 == unt6 && unt6 == unt7);

Unit unt8 = Unit.Parse("kg*m/s^(kg)");//will raise error, a unit cannot be placed in power 

//In Action I:

Measurable meu0 = Measurable.Parse("100 N");
Measurable meu1 = "100 N";
Measurable meu2 = new Measurable(unt0, 100);

Debug.Assert(meu0 == meu1);

Measurable meu3 = meu0.ConvertTo("kgf");
Debug.Assert(meu3.Amount == 1000);
Debug.Assert(meu3.Unit == "kgf");
 

//In action II, calculating average acceleration
 

Measurable deltax = "100 m";
Measurable deltaT = "10 sec";
Measurable scUnit = "2 kg/kg";

Measurable avgAccl = deltax / (deltaT ^ scUnit);//which is 1 m/sec^2

Debug.Assert(avgAccl.Amount == 1);
Debug.Assert(avgAccl.Unit == "m/  sec^2");

//In action III: creating new units

Unit bit = Unit.CreateNew("b");
Unit B = bit * 8;
Unit.Register(ref B, "B");
Unit KB = B * 1024;
Unit.Register(ref KB, "KB");
Unit MB = KB * 1024;
Unit.Register(ref MB, "MB");
Unit GB = MB * 1024;
Unit.Register(ref GB, "GB");
Unit TB = GB * 1024;
Unit.Register(ref TB, "TB");

Unit bps = bit / Unit.GetRegisteredUnit("sec");
Unit.Register(ref bps, "bps");
Measurable smb = "100 MB/sec";
Measurable sb = smb.ConvertTo("bps");// 100 MB = 100*1024*1024*8 b = 838860800 b

Debug.Assert(sb.Amount == 838860800);
Debug.Assert(sb.Unit == bit / "sec");

Constants

There is also a static class named UnitConversionLib.Consts which holds some useful coefficients:

C#
public static class Consts
{
    public static readonly double Yotta = 1e+24;
    public static readonly double Zetta = 1e+21;
    public static readonly double Exa = 1e+18;
    public static readonly double Peta = 1e+15;
    public static readonly double Terra = 1e+12;
    public static readonly double Giga = 1e+9;
    public static readonly double Mega = 1e+6;
    public static readonly double Kilo = 1e+3;
    public static readonly double Hecto = 1e+2;
    public static readonly double Deca = 1e+1;

    public static readonly double Deci = 1e-1;
    public static readonly double Centi = 1e-2;
    public static readonly double Milli = 1e-3;
    public static readonly double Micro = 1e-6;
    public static readonly double Nano = 1e-9;
    public static readonly double Pico = 1e-12;
    public static readonly double Femto = 1e-15;
    public static readonly double Atto = 1e-18;
    public static readonly double Zeppto = 1e-21;
    public static readonly double Yocto = 1e-24;
}

You can use UnitConversionLib.Consts class like this:

C#
Unit km = Unit.Parse("m") * Consts.Kilo;

Exceptions

Not all errors are throwing appropriated Exception in UnitConversionLib and it needs more time to fix the code. However, there is a UnitConversionLibException class and a UnitParsingException that will be thrown in errors (but not all of them) with appropriated message (accessible from Exception.Message property).

Conclusion

This article is about how to use open source library ‘UnitConversionLib’ which stands for working with measurable quantities and unit conversion in .NET. You can download it from Codeplex with going to this link. And clicking on the download button on the right side of the page.

History

  • 18th June, 2014: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)