14

Possible Duplicate:
Engineering notation in C#?

Whether a metric prefix is preferable to the scientific notation may be up for debate but i think it has its use-cases for physical units.

I had a look around but it seems .NET does not have anything like that built in, or am i mistaken about that? Any method of achieving that would be fine.

As a clarification: The goal is to display any given number as a floating point or integer string with a value between 1 and 999 and the respective metric prefix.

e.g.

1000 -> 1k
0.05 -> 50m

With some rounding:

1,436,963 -> 1.44M

Community
  • 1
  • 1
H.B.
  • 166,899
  • 29
  • 327
  • 400
  • 1
    It's not really clear what you are asking here. Please provide samples of input and expected output. – Daniel Hilgarth Aug 29 '12 at 15:11
  • Do you mean like converting `12345000` to `12.34M` rather than `1.234e007`? As far as I know there is no built in support for that. – verdesmarald Aug 29 '12 at 15:14
  • @DanielHilgarth: Added some clarification. – H.B. Aug 29 '12 at 15:17
  • @veredesmarald: Yes, that is what it seemed like to me as well. – H.B. Aug 29 '12 at 15:17
  • @H.B.: Thanks. Unfortunatelly, I don't know of any library that does this. – Daniel Hilgarth Aug 29 '12 at 15:18
  • @DanielHilgarth: Well, i think that it should be fairly easy to implement with a dictionary for the orders of magnitude, i was hoping for something .NET internal but i think it isn't there. Maybe i will implement it myself... – H.B. Aug 29 '12 at 15:19

3 Answers3

14

Try this out. I haven't tested it, but it should be more or less correct.

public string ToSI(double d, string format = null)
{
    char[] incPrefixes = new[] { 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
    char[] decPrefixes = new[] { 'm', '\u03bc', 'n', 'p', 'f', 'a', 'z', 'y' };

    int degree = (int)Math.Floor(Math.Log10(Math.Abs(d)) / 3);
    double scaled = d * Math.Pow(1000, -degree);

    char? prefix = null;
    switch (Math.Sign(degree))
    {
        case 1:  prefix = incPrefixes[degree - 1]; break;
        case -1: prefix = decPrefixes[-degree - 1]; break;
    }

    return scaled.ToString(format) + prefix;
}
H.B.
  • 166,899
  • 29
  • 327
  • 400
Thom Smith
  • 13,916
  • 6
  • 45
  • 91
  • 2
    Probably could use some error handling for very small or large numbers but overall it works. – H.B. Aug 29 '12 at 16:18
  • 2
    It's useful to check at the entry of function, if `d` is 0, because otherwise `degree` takes `-Infinity` value. – LucaG Feb 13 '18 at 11:41
  • 1
    I can't emphasize enough here that this will crash in case `d` is zero (as @LucaG) already hinted. Negating `-Infinity` or in this particular case `Int32.MinValue` will result in an Overflow exception. – greyhairredbear Apr 28 '20 at 13:27
  • @LPeteR90 Feel free to submit an edit. I haven't touched C# in years, myself. – Thom Smith Apr 28 '20 at 17:38
1

According to these SO Articles and to my own research, there is no native way to format numbers in metric units. You will need to write your own methods to parse the units and append the relevant metric measurement, such as for instance an expanded example of this interface tutorial at MSDN. You can also try to find a metric units coding library to use for development.

Community
  • 1
  • 1
Scott Conover
  • 1,421
  • 1
  • 14
  • 27
1

Create an extension method for each numeric type. You would call ToStringMetric() for you custom formatting.

public static class Int32Extensions
{
        public static string ToStringMetric(this Int32 x) { return (x / 1000).ToString() + " K"; }
}
paparazzo
  • 44,497
  • 23
  • 105
  • 176