如何用上标的幂格式化科学记数法中的数字
How to format numbers in scientific notation with powers in superscript
我需要这样写值:
9.6 x 10²
9.6 x 10¹²
我想知道是否有办法像上面那样在字符串中格式化数字。
您必须从您使用的代码页中找到合适的字符,例如 UTF-8:
string superScript2 = "²";
字符串中没有格式化这回事,它只是所有数据。
作为我上面评论的跟进 - 像这样做你需要的事情:
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://docs.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#),然后转换回字符串并使用 "x 10" 作为新分隔符将两部分组合在一起。
我假设您希望根据您的示例将值精确到个位数,并且没有前置 + 号。如果您需要其他任何东西,您可以将格式作为参数传递。上标+的代码是'\u207A'。这里有一个 link(在撰写本文时)给出了上标代码列表:http://unicode.org/charts/PDF/U2070.pdf
试试这个:
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¹
之类的情况)。作为奖励,可以通过分别为 4 位或 5 位提供 g4
或 g5
等格式代码,将数字格式化为特定数量的有效数字。
- 它可以处理负数或正数
- 它可以处理 10 的负指数或正指数
- 可以格式化尾数
- 它可以处理
NAN
或 Inf
。
- 它是可重用的扩展形式
我需要这样写值:
9.6 x 10²
9.6 x 10¹²
我想知道是否有办法像上面那样在字符串中格式化数字。
您必须从您使用的代码页中找到合适的字符,例如 UTF-8:
string superScript2 = "²";
字符串中没有格式化这回事,它只是所有数据。
作为我上面评论的跟进 - 像这样做你需要的事情:
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://docs.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#),然后转换回字符串并使用 "x 10" 作为新分隔符将两部分组合在一起。
我假设您希望根据您的示例将值精确到个位数,并且没有前置 + 号。如果您需要其他任何东西,您可以将格式作为参数传递。上标+的代码是'\u207A'。这里有一个 link(在撰写本文时)给出了上标代码列表:http://unicode.org/charts/PDF/U2070.pdf
试试这个:
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¹
之类的情况)。作为奖励,可以通过分别为 4 位或 5 位提供 g4
或 g5
等格式代码,将数字格式化为特定数量的有效数字。
- 它可以处理负数或正数
- 它可以处理 10 的负指数或正指数
- 可以格式化尾数
- 它可以处理
NAN
或Inf
。 - 它是可重用的扩展形式