3

I have a label to show an unsigned integer, and it has a maximum lenght. I'd like to format numbers to be displayed like this:

1           = "1"
1000        = "1,000"
12400       = "12.4k"
101,800,000 = "102M" // !!!
1,849,000   = "1.85M"

So, I ended up with a string with maximum lenght 5.

My range is from 0 to 199,999,999.

Is there a way to do this without treating many cases, i.e., many intervals?

Roberto
  • 11,557
  • 16
  • 54
  • 68
  • 1
    The requirements for your problem seems too specific for it to have an already existing solution doing exactly what you want it to do. You will probably have to write your own function. Also, how does 1.800.000 = "1,85M"? And if your range goes to a maximum of 1,999,999 how can you get 101.800.000 = "102M" ? – Shadowxvii Aug 15 '12 at 14:33
  • is 101.800.000 a valid case, taking into account "range is from 0 to 1,999,999." ? – Ilya Ivanov Aug 15 '12 at 14:33
  • sorry, I messed with the range, with the 1.85M and with the separators (in my language "." is "," and "," is ".")... – Roberto Aug 15 '12 at 14:38
  • Personally I would write an extension method for the unsigned integer class, which would have the logic built in. I have something similar for dates, i.e. "1 day ago", "14 days ago", "3 months ago" etc for writing friendly formatting on DateTime. – KingCronus Aug 15 '12 at 14:40
  • You only need as many cases as many deviations you plan on implementing.. So in your case, you only need. 1024 -> 1,024, 12345 -> 12.4k, 123456 -> 123k, 1234567 -> 1.2m, 12345678 -> 12m. 5 Cases has you covered up to one billion. – Anonymous Aug 15 '12 at 14:45

2 Answers2

2

I'm probably too late, but here's an extension method which returns numbers formatted as you want:

public static string ToShortString(this int n)
{
    if (n >= 1e8)
    {
        return (Math.Round((double)n / 1e6, 0)).ToString() + "M";
    }
    else if (n >= 1e7)
    {
        return (Math.Round((double)n / 1e6, 1)).ToString() + "M";
    }
    else if (n >= 1e6)
    {
        return (Math.Round((double)n / 1e6, 2)).ToString() + "M";
    }
    else if (n >= 1e5)
    {
        return (Math.Round((double)n / 1e3, 0)).ToString() + "K";
    }
    else if (n >= 1e4)
    {
        return (Math.Round((double)n / 1e3, 1)).ToString() + "K";
    }
    else if (n >= 1e3)
    {
        return n.ToString("##,#");
    }
    else
    {
        return n.ToString();
    }
}

Tests:

Console.WriteLine((5).ToShortString());         // displays 5
Console.WriteLine((55).ToShortString());        // displays 55
Console.WriteLine((555).ToShortString());       // displays 555
Console.WriteLine((5555).ToShortString());      // displays 5,555
Console.WriteLine((55555).ToShortString());     // displays 55.6K
Console.WriteLine((555555).ToShortString());    // displays 556K
Console.WriteLine((5555555).ToShortString());   // displays 5.56M
Console.WriteLine((55555555).ToShortString());  // displays 55.6M
Console.WriteLine((555555555).ToShortString()); // displays 556M
david.s
  • 11,283
  • 6
  • 50
  • 82
1

This answer here shows how to do it in a variety of ways: Round numbers with K suffix

Unfortunately I don't know of any way to do it without at least a fair amount of cases. But some of the answers in the above question do it rather elegantly and with a minimum amount of code.

Community
  • 1
  • 1
XN16
  • 5,679
  • 15
  • 48
  • 72