Click here to Skip to main content
Click here to Skip to main content

Tagged as

Converting a value to an SI unit string

, 2 Jul 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

OriginalGriff
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?
Follow on   Google+

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web01 | 2.8.141022.2 | Last Updated 2 Jul 2012
Article Copyright 2012 by OriginalGriff
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid