.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