The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 4,225 other subscribers

.NET/C#: UnitPrefixes class that facilitates distinguishing decimal and binary file/drive/memory size (mega versus mibi, etc)

Posted by jpluimers on 2013/08/14

Everyone knows there is a size difference between a gigabyte of memory, and a gigabyte of disk space.

The former is 1024*1024*1024, the latter is 1000*1000*1000.

To facilitate this, I’ve created a C# class UnitPrefixes containing quite a few constants and readonly values.

The class is below, but a few interesting facts first:

  • Most values are const, but a few are readonly static variables because they cannot calculated at compile time (the C# compiler by design does very limited calculations at compile time; it is complex enough as it already is).
    As Jon Skeet explains, there are some other differences between const and readonly static, which is why I favour const.
  • Though all consts are positive, I could have used UInt32 and UInt64, but the .NET framework favours signed Int32 and Int64 types for parameters, so to avoid casting, I used the signed ones.
  • There is no Int128 or UInt128, but there is System.Numerics.BigInteger which I use for values too large for 64-bit integers.
    Note that BigInteger is relatively new, so this code will only work in C# 4 or higher, and requires .NET 4 or higher.
    This is also the place where I use the public readonly static fields, as I need to call the BigInteger constructor to initialize it.
  • I used the Decimal type, as the mantissa holds up to 28 digits of accuracy.

I used the Wikipedia pages Binary Prefix and Metric Prefix (I could also have used File Size) for the unit names and abbreviations.

Note that BitsPerByte is a const I needed too, and I will probably add constants for 512 and 4096, as you see those often in computing as well.

The below sample code is also available as a changeset on BeSharp.CodePlex.com.

using System;
using System.Numerics;

namespace BeSharp.Numerics
{
    public static class UnitPrefixes
    {
        public const UInt64 BitsPerByte = 8;

        #region Binary

        public const Int32 kibi = 1024;
        public const Int32 mebi = kibi * kibi;
        public const Int32 gibi = kibi * mebi;
        public const Int64 tebi = kibi * ((Int64)gibi);
        public const Int64 pebi = kibi * tebi;
        public const Int64 exbi = kibi * pebi;
        public readonly static BigInteger zebi = kibi * ((BigInteger)exbi);
        public readonly static BigInteger yobi = kibi * zebi;

        public const Int32 KiB = kibi;
        public const Int32 MiB = mebi;
        public const Int32 GiB = gibi;
        public const Int64 Ti = tebi;
        public const Int64 Pi = pebi;
        public const Int64 Ei = exbi;
        public readonly static BigInteger Zi = zebi;
        public readonly static BigInteger Yi = yobi;

        #endregion

        #region Metric

        public const Int32 one = 1;
        public const Int32 deca = 10;
        public const Int32 hecto = 100;
        public const Int32 kilo = 1000;
        public const Int32 mega = kilo * kilo;
        public const Int32 giga = kilo * mega;
        public const Int64 tera = kilo * ((Int64)giga);
        public const Int64 peta = kilo * tera;
        public const Int64 exa = kilo * peta;
        public readonly static BigInteger zetta = kilo * ((BigInteger)exa);
        public readonly static BigInteger yotta = kilo * zetta;

        public const Int32 h = hecto;
        public const Int32 k = kilo;
        public const Int32 M = mega;
        public const Int32 G = giga;
        public const Int64 T = tera;
        public const Int64 P = peta;
        public const Int64 E = exa;
        public readonly static BigInteger Z = zetta;
        public readonly static BigInteger Y = yotta;

        public const Decimal deci = 1m / ((Decimal)deca);
        public const Decimal centi = deci / deca;
        public const Decimal milli = centi / deca;
        public const Decimal micro = milli / milli;
        public const Decimal nano = milli / micro;

        public const Decimal d = deci;
        public const Decimal c = centi;
        public const Decimal m = milli;
        public const Decimal μ = micro;
        public const Decimal n = nano;

        #endregion
    }
}

–jeroen

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

 
%d bloggers like this: