Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Converting a value to an SI unit string

0.00/5 (No votes)
2 Jul 2012 1  
Converting a value to an SI unit string.

Introduction

Displaying some data statistics, I wanted a way to display the bytes involved in terms of SI units: Kilo, Mega, Giga and so on, just to give a feel for the number size. So I set to to write a simple method: if...else if...else if...   ...boring...and easy to get wrong! 

Then I remembered something from school... 

Background

I didn't think I remembered much from my schooling - it was a long time ago, and I haven't used it since - but then I remembered what a Log is:

Logn(x) = y

means:

"How many times do I have to multiply 'n' by itself to get 'x'?"

So, if you take the Log base 10 of any number, the integral portion of the result is the number of digits between the highest value digit, and the decimal point.

So

Log10(100) is 2

Log10(1000) is 3

Log10(1000000) is 6

and the integral part of Log10(845405107478) is 11

In mathematics parlance, this is called the "characteristic". 

Otherwise known as the exponent of the original value...Ah!

Using the code 

using System;
 
namespace UtilityControls
{
public static partial class ExtensionMethods
{
    /// <summary>
    /// Prefixes for numbers
    /// Since a long can only hold 9.2E18 (ie., exa territory) we
    /// don't need zetta, yotta, xona, weka, vunda, uda, treda, sorta, 
    /// rinta, quexa, pepta, ocha, nena, minga, or luma
    /// Just so you know...
    /// </summary>
    private static string[] sizes = { " ", "Kilo", "Mega", 
            "Giga", "Tera", "Peta", "Exa" };
    /// <summary>
    /// Format a set of bytes into a human readable format
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static string ToReadableSIUnit(this long value)
    {
        // Get the exponent
        // Since logn(x) = y means "Multiply 'n' by itself 'y' times to get 'x'",
        // the integer part of the log base 10 of any number is the exponent.
        // (This is called the "characteristic" in math parlance)
        // Since we are using longs which don't have a faractional part, this can't be negative.
        int exponent = (int)Math.Log10(value);
        int group = exponent / 3;
        if (group >= sizes.Length)
        {
            throw new ApplicationException("64 bit numbers are bigger than they should be...");
        }
        double divisor = Math.Pow(10, group * 3);
        return string.Format("{0:0.0} {1}", value / divisor, sizes[group]);
    }
}
}

Include the static class in your application, and use the extension method:

long val = 845405107478;
Console.WriteLine("{0}bytes", val.ToReadableSIUnit());

Will print:

854.4Gigabytes

How it works

Log base 10 is used to get the exponent, and an integer divide changes that into a Engineering style group of three (so E0 (digits), E1(tens) and E2(hundreds) are in group 0; E3, E4 and E5 are in group 1, and so on).

The group is used to generate the divisor to format the original number as just three digits to the right of the decimal point, and then as an index into the strings array directly to provide the suffix. 

Additional versions are provided to give short suffixes in the download file. 

Warnings 

This isn't going to be the fastest version - I suspect that it will be slower than the equivalent if...else if...else if... version, simply because of the need to calculate the log and power functions.

However, since it is only going to be used for presentation of a number to a user, that may not matter to you! 

Maybe I did pay more attention at school than I thought I did...

History

Original version

V1.0 Type changed from Article to Tip - not sure how it became an article in the first place... 

V1.1 Minor formatting problem in the "Log(100) is 2" etc. section. 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here