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

Tagged as

Go to top

A simple "human scale" number to string converter

, 25 May 2014
Rate this:
Please Sign up or sign in to vote.
I needed to show file sizes in a "human friendly format" recently, so I thought I'd knock up a simple method to do it. So the file sizes such as 10123456789 bytes would display as 10.1Gb and so forth.

Introduction

I needed to show file sizes in a "human friendly format" recently, so I thought I'd knock up a simple method to do it. So the file sizes such as 10123456789 bytes would display as 10.1Gb and so forth. Simple, but a pain, since it breaks your concentration to "knock up" a method. I'm sure there are other versions out there, but...some of them are far too complicated for their own good!

The code

Easy to read, I think: it uses an array of ISO suffixes (in ISO they are prefixes, because they come before the quantity type: "G" is the prefix, "b" is the bytes in "12.3 Gb")

        /// <summary>
        /// Suffix size values (ISO only goes up to "Yotta", but a 64bit int 
        /// can't even get there - the last two are for completeness.)
        /// </summary>
        /// 
        private static string[] suffixes = new string[] { "", "k", "M", "G", "T", "P", "E", "Z", "Y" };
        /// <summary>
        /// Converts a long value to a human scale count
        ///        Number  Human Scale
        ///             1  1
        ///            10  10
        ///           101  101
        ///          1012  1.01k
        ///         10123  10.1k
        ///        101234  101k
        ///       1012345  1.01M
        ///      10123456  10.1M
        ///     101234567  101M
        ///    1012345678  1.01G
        ///             ....
        /// </summary>
        /// <param name="value">Value to scale</param>
        /// <param name="suffix">If supplied, appended to the output string</param>
        /// <param name="spacer">If supplied, it separates the numbers and the ISO size indicator</param>
        /// <param name="positiveIndicator">If supplied, it prefixes the number</param>
        /// <returns></returns>
        public static string HumanScale(long value, string suffix = "", string spacer = "", string positiveIndicator = "")
            {
            string result = Math.Abs(value).ToString();
            int digits = result.Length;
            if (digits >= 4)
                {
                digits--;       // Groups = (Length - 1) / sizeOfGroup; 
                                // digitsBeforeDecimal = ((Length - 1) % 3) + 1
                                // This avoids testing and "move down" of groups count
                                // when we don't want a decimal at all: 123M for example.
                int groups = digits / 3;
                int digitsBeforeDecimal = digits % 3;
                StringBuilder sb = new StringBuilder();
                foreach (char c in result.Substring(0, 3))
                    {
                    if (digitsBeforeDecimal == -1) sb.Append(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
                    digitsBeforeDecimal--;
                    sb.Append(c);
                    }
                result = string.Format("{0}{1}{2}{3}", sb, spacer, suffixes[groups], suffix);
                }
            return string.Format("{0}{1}", value < 0 ? System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NegativeSign : positiveIndicator, result);
            }

Using it is also simple:

            long l = 1;
            for (int i = 0; i <= 24; i++)
                {
                Console.WriteLine("{0,2} {1,24}  {2}", i, l, HumanScale(l));
                l = (l * 10) + (i % 10);
                }

Generates:

 0                        1  1
 1                       10  10
 2                      101  101
 3                     1012  1.01k
 4                    10123  10.1k
 5                   101234  101k
 6                  1012345  1.01M
 7                 10123456  10.1M
 8                101234567  101M
 9               1012345678  1.01G
10              10123456789  10.1G
11             101234567890  101G
12            1012345678901  1.01T
13           10123456789012  10.1T
14          101234567890123  101T
15         1012345678901234  1.01P
16        10123456789012345  10.1P
17       101234567890123456  101P
18      1012345678901234567  1.01E
19     -8323287284697205938  -8.32E
20      9000847521575698709  9.00E
21     -2225245152790770990  -2.22E
22     -3805707454198158283  -3.80E
23     -1163586394562479596  -1.16E
24      6810880128084755659  6.81E

Note that the long value overflows long before Yottabytes are reached!

History

2014-05-25 Original version

2014-05-25 XML comments un-mucked up. Editor removed closing tags, and so forth - so they would have been invalid in Visual Studio when copy / pasted. I do dislike this editor, sometimes...

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

 
QuestionShortening made easier PinmemberMember 108445049-Jun-14 12:46 
SuggestionWhat about using the OS functions? PinprotectorDaveAuld25-May-14 19:11 
GeneralRe: What about using the OS functions? PinprofessionalRavi Bhavnani26-May-14 2:37 
QuestionVery useful... Pinmemberbombersa25-May-14 6:44 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 25 May 2014
Article Copyright 2014 by OriginalGriff
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid