.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 102410241024, the latter is 100010001000.
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 comment