Click here to Skip to main content
15,885,244 members
Articles / Programming Languages / C#
Tip/Trick

Converting a value to an SI unit string

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
2 Jul 2012CPOL2 min read 13.7K   72   3   2
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 

C#
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:

C#
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO
Wales Wales
Born at an early age, he grew older. At the same time, his hair grew longer, and was tied up behind his head.
Has problems spelling the word "the".
Invented the portable cat-flap.
Currently, has not died yet. Or has he?

Comments and Discussions

 
QuestionExcellent Pin
Mike Hankey10-Mar-15 21:57
mveMike Hankey10-Mar-15 21:57 
AnswerRe: Excellent Pin
OriginalGriff10-Mar-15 22:54
mveOriginalGriff10-Mar-15 22:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.