如何使用上标格式化科学计数法中的数字和指数

15

我需要写入像这样的数值:

9.6 x 10²
9.6 x 10¹²

我需要知道是否有一种方法可以在字符串中格式化数字,就像上面显示的那样。


3
你的目标平台是哪个?WinForms、WPF、Html、UWP等等?字符串本身只是数据,不包含任何有关呈现的信息。你可以直接应用的唯一格式化方式是科学计数法:https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings - Marco
1
需要使用那种格式吗?还是指数格式(例如9.6E2)可接受? - PaulF
4
String.Format() 方法中有一个指数数字格式说明符,它可以给出带有指数的数字(如 1.2346e+004),虽然不完全与您的示例格式相同,但具有相同的含义。更多信息:https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#EFormatString - Diado
1
@RenanPrológica 如果要打印,那么它必须是一个字符串吗?还是可以是格式化文本/图像等其他类型? - Konrad Rudolph
1
@RenanPrológica 有关指数如何打印的规定吗?例如,数字可能有最小物理尺寸。 - Andrew Morton
显示剩余3条评论
3个回答

12

你需要从你正在使用的代码页中找到合适的字符,例如 UTF-8

string superScript2 = "²";

字符串中不存在格式化,它只是所有数据。


10

试试这个:

    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)}";
        }
    }

作为一个测试案例运行

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;
    }
}

输出结果为:

  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²⁴

这个算法并不是最优化的,但它确实完成了工作。幂指数采用工程表示法(仅为3的倍数,以避免出现像10¹这样的东西)。作为奖励,可以通过提供格式代码(如g4g5)来将数字格式化为指定数量的有效数字,分别为4或5位。

  • 它可以处理正数或负数
  • 它可以处理正数或负数的10次方指数
  • 它可以格式化尾数
  • 它可以处理NANInf
  • 它使用扩展形式以便于重复使用

使用工程计数法表示数字时,加号比纯科学计数法更实用。 - Navin
1
@Navin - 我同意。相比于 1.23e2,我更喜欢 123 - John Alexiou

1
作为对我上面评论的跟进 - 像这样的东西是否满足您的要求:
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);
}

请参见:https://dotnetfiddle.net/dX7LAF

根据我上面的评论 - 数字首先被转换为指数格式字符串(https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#EFormatString),然后在指数分隔符'E'上拆分该字符串。第一个数组是数字部分,第二个是它所提高的10的幂次 - 这使用我给出的链接中的技术之一转换为上标字符(Convert a string/integer to superscript in C#),再将其转换回字符串,并使用“x 10”作为新的分隔符组合两个部分。

我已经假设你希望按照你的示例将值精确到个位数,且没有前导的+号。如果需要其他内容,您可以将格式作为参数传递。上标 + 的代码为 '\u207A'。这里有一个链接(在撰写本文时)提供了上标代码列表:http://unicode.org/charts/PDF/U2070.pdf

你可能想要透露你使用了这个答案的部分内容。 - Patrick Hofman
@PatrickHofman:正如我在评论中提到的建议,我认为这是不必要的 - 但我可以看出它可能会有用。 - PaulF
1
如果评论被删除,就不会有任何可见的来源了。这就是我建议的原因。此外,你不能期望那些阅读你的答案的人去查看所有的评论以寻找披露信息。 - Patrick Hofman
哎呀,你真的必须部分解析另一个格式化程序的输出来做到这一点吗?那个输出不是为机器消费而设计的! - Navin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接