15

I need to write values like:

9.6 x 10²
9.6 x 10¹²

I need to know if there is a way to format numbers as above in a string.

Boann
  • 48,794
  • 16
  • 117
  • 146
  • 3
    Which platform are you targeting? WinForms, WPF, Html, UWP, ...? strings in itself are just data and contain no information about presentation. The only formatting you can apply yourself out of the box is the scientifiy notation: https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings – Marco Jan 02 '18 at 12:06
  • 1
    Does it need to be that format - or is the [exponential format](https://stackoverflow.com/questions/9273176/representing-numbers-in-exponential-form) (e.g. 9.6E2) acceptable – PaulF Jan 02 '18 at 12:10
  • 4
    There's an exponent numeric format specifier which you can use with `String.Format()` which will give you the number with its exponent (i.e. `1.2346e+004`) - not quite the same as your example format, but has the same meaning. More info: https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#EFormatString – Diado Jan 02 '18 at 12:10
  • The platform I'm going to use is Windows Forms, it has to be exactly in 10² format because it will be printed on medicine packaging and will not allow you to express it in another type of format. –  Jan 02 '18 at 12:14
  • You could create a method that converts to the exponential format & then use Regex or Linq to convert the exponential part to " x 10" followed by the superscript equivalent numbers - see this : https://stackoverflow.com/questions/6431601/convert-a-string-integer-to-superscript-in-c-sharp – PaulF Jan 02 '18 at 12:46
  • Do you also want support for negative exponents? – John Alexiou Jan 02 '18 at 13:24
  • 1
    @RenanPrológica If it’s printed, then does it need to be a string or can it be a formatted text/an image/…? – Konrad Rudolph Jan 02 '18 at 15:49
  • 1
    @RenanPrológica Are there any regulations about how the exponent is to be printed? For example, there might be a minimum physical size for the digits. – Andrew Morton Jan 02 '18 at 16:32

3 Answers3

12

You have to find the appropriate character from the code page you are using, for example UTF-8:

string superScript2 = "²";

There is no such thing as formatting in a string, it is just all data.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
10

Try this:

    public static string Eng(this double x, string format="g")
    {
        const string sup_signs = "⁺⁻⁼⁽⁾ⁿ";
        const string sup_digits = "⁰¹²³⁴⁵⁶⁷⁸⁹";

        if(double.IsNaN(x) || double.IsInfinity(x))
        {
            return x.ToString();
        }

        int num_sign = Math.Sign(x);
        x = Math.Abs(x);
        // group exponents in multiples of 3 (thousands)
        int exp = (int)Math.Floor(Math.Log(x, 10)/3)*3;
        // otherwise use:
        // int exp = (int)Math.Floor(Math.Log(x, 10));
        // and handle the exp==1 case separetly to avoid 10¹
        x*= Math.Pow(10, -exp);
        int exp_sign = Math.Sign(exp);
        exp = Math.Abs(exp);
        // Build the exponent string 'dig' from right to left
        string dig = string.Empty;
        while(exp>0)
        {
            int n = exp%10;
            dig = sup_digits[n] + dig;
            exp = exp/10;
        }
        // if has exponent and its negative prepend the superscript minus sign
        if(dig.Length>0 && exp_sign<0)
        {
            dig = sup_signs[1] + dig;
        }
        // prepend answer with minus if number is negative
        string sig = num_sign<0 ? "-" : "";            
        if(dig.Length>0)
        {
            // has exponent
            return $"{sig}{x.ToString(format)}×10{dig}";
        }
        else
        {
            // no exponent
            return $"{sig}{x.ToString(format)}";
        }
    }

As a test case run

static void Main(string[] args)
{
    // Type code here.
    double x = Math.PI/50e5;
    for(int i = 0; i < 20; i++)
    {
        // Format output to 12 wide column, right aligned
        Debug.WriteLine($"{ Eng(x, "g4"),12}");
        x*=50;
    }
}

with the output:

  628.3×10⁻⁹
  31.42×10⁻⁶
  1.571×10⁻³
  78.54×10⁻³
       3.927
       196.3
   9.817×10³
   490.9×10³
   24.54×10⁶
   1.227×10⁹
   61.36×10⁹
  3.068×10¹²
  153.4×10¹²
   7.67×10¹⁵
  383.5×10¹⁵
  19.17×10¹⁸
  958.7×10¹⁸
  47.94×10²¹
  2.397×10²⁴
  119.8×10²⁴

By no means optimized, but it does the job. The exponents are in engineering form (multiples of 3 only, in order to avoid things like 10¹). As a bonus, the number can be formatted to a specific number of significant digits by supplying a format code like g4 or g5 for 4 or 5 digits respectively.

  • It can handle negative or positive numbers
  • It can handle negative or positive exponents of 10
  • In can format the mantissa
  • It can handle NAN or Inf.
  • It's in extension form for re-usability
John Alexiou
  • 28,472
  • 11
  • 77
  • 133
1

As a follow up to my comment above - does something like this do what you require :

public String FormatAs10Power(decimal val)
{
  string SuperscriptDigits = "\u2070\u00b9\u00b2\u00b3\u2074\u2075\u2076\u2077\u2078\u2079";
  string expstr = String.Format("{0:0.#E0}", val);

  var numparts = expstr.Split('E');
  char[] powerchars = numparts[1].ToArray();
  for (int i = 0; i < powerchars.Length; i++)
  {
    powerchars[i] = (powerchars[i] == '-') ? '\u207b' : SuperscriptDigits[powerchars[i] - '0'];
  }
  numparts[1] = new String(powerchars);
  return String.Join(" x 10",numparts);
}

See : https://dotnetfiddle.net/dX7LAF

As per my comment above - the number is first converted to an exponential format string (https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#EFormatString), that string is then split on the exponential separator 'E'. The first array is the numeric part, the second the power of 10 to which it is raised - this is converted to superscript characters using one of the techniques of the link I gave (Convert a string/integer to superscript in C#), converted back to a string & the two parts combined using "x 10" as the new separator.

I have assumed you want the value to single digit precision as per your example with no preceding + sign. If you need anything else you could pass the format as a parameter. The code for superscript + is '\u207A'. There is a link here (at the time of writing) giving the list of superscript codes : http://unicode.org/charts/PDF/U2070.pdf

PaulF
  • 6,673
  • 2
  • 18
  • 29
  • You might want to disclose you took parts of [this answer](https://stackoverflow.com/a/6431614/993547). – Patrick Hofman Jan 02 '18 at 13:24
  • @PatrickHofman: As I had suggested what to do in the comment I referred to, I thought this was unnecessary - but I can see it could be of use. – PaulF Jan 02 '18 at 13:32
  • 1
    If the comment gets deleted, there is no visible source any more. So that is why I suggested it. Also, you can't expect someone who reads your answer to read all comments to look for a disclosure. – Patrick Hofman Jan 02 '18 at 13:32
  • Eww, do you really have to partially parse the output of another formatter to do this? That output is not for machine consumption! – Navin Jan 02 '18 at 18:17