字符串格式数字以百万、千为单位四舍五入
String format numbers to millions, thousands with rounding
我正在尝试设置显示价格的格式,我想显示一个带有百万 (M) 或千 (K) 后缀的数字,但最多只显示 3 个向下舍入的值。
我发现 this question 非常接近我想要的,但不处理舍入(具体来说,总是向下舍入)
同样,with this question 您无法控制舍入。
示例 input/expected 输出:
1 = 1
10 = 10
100 = 100
1000 = 1K
100000 = 100K
125000 = 125K
125900 = 125K
1000000 = 1M
1250000 = 1.25M
1258000 = 1.25M
10000000 = 10M
10500000 = 10.5M
100000000 = 100M
100100000 = 100M
我基本上只想显示 3 个值。
我看不出如何使用 "," custom specifier 和指定舍入。
我最初的想法是我需要结合使用上述方法,Math.Floor 和一些 .ToString() 格式化魔法,但我不确定从哪里开始。
有人可以帮我吗?
提前致谢。
结合您链接到的其他问题中的一种格式化技术,这应该会有所帮助。
internal long MaxThreeSignificantDigits(long x)
{
int i = (int)Math.Log10(x);
i = Math.Max(0, i - 2);
i = (int)Math.Pow(10, i);
return x / i * i;
}
编辑:
好的,这个怎么样?
Console.WriteLine(SO30180672.FormatNumber(1));
Console.WriteLine(SO30180672.FormatNumber(12));
Console.WriteLine(SO30180672.FormatNumber(123));
Console.WriteLine(SO30180672.FormatNumber(1234));
Console.WriteLine(SO30180672.FormatNumber(12345));
Console.WriteLine(SO30180672.FormatNumber(123456));
Console.WriteLine(SO30180672.FormatNumber(1234567));
Console.WriteLine(SO30180672.FormatNumber(12345678));
Console.WriteLine(SO30180672.FormatNumber(123456789));
以下是从此处复制的部分内容:
internal class SO30180672
{
internal static string FormatNumber(long num)
{
num = MaxThreeSignificantDigits(num);
if (num >= 100000000)
return (num / 1000000D).ToString("0.#M");
if (num >= 1000000)
return (num / 1000000D).ToString("0.##M");
if (num >= 100000)
return (num / 1000D).ToString("0k");
if (num >= 100000)
return (num / 1000D).ToString("0.#k");
if (num >= 1000)
return (num / 1000D).ToString("0.##k");
return num.ToString("#,0");
}
internal static long MaxThreeSignificantDigits(long x)
{
int i = (int)Math.Log10(x);
i = Math.Max(0, i - 2);
i = (int)Math.Pow(10, i);
return x / i * i;
}
}
编辑 2 - 非常感谢@Rhexis
internal class SO30180672
{
internal static void RunTest()
{
Console.WriteLine(FormatNumber(1));
Console.WriteLine(FormatNumber(10));
Console.WriteLine(FormatNumber(100));
Console.WriteLine(FormatNumber(1000));
Console.WriteLine(FormatNumber(10000));
Console.WriteLine(FormatNumber(100000));
Console.WriteLine(FormatNumber(125000));
Console.WriteLine(FormatNumber(125900));
Console.WriteLine(FormatNumber(1000000));
Console.WriteLine(FormatNumber(1250000));
Console.WriteLine(FormatNumber(1258000));
Console.WriteLine(FormatNumber(10000000));
Console.WriteLine(FormatNumber(10500000));
Console.WriteLine(FormatNumber(100000000));
Console.WriteLine(FormatNumber(100100000));
}
private static string FormatNumber(long num)
{
// Ensure number has max 3 significant digits (no rounding up can happen)
long i = (long)Math.Pow(10, (int)Math.Max(0, Math.Log10(num) - 2));
num = num / i * i;
if (num >= 1000000000)
return (num / 1000000000D).ToString("0.##") + "B";
if (num >= 1000000)
return (num / 1000000D).ToString("0.##") + "M";
if (num >= 1000)
return (num / 1000D).ToString("0.##") + "K";
return num.ToString("#,0");
}
}
由于格式本质上会根据范围发生变化,因此您很可能需要类似于下面的一些条件格式。我只测试了提供的样本集,因此请确保它适用于所有预期值范围。
class Program
{
static void Main(String[] args)
{
Console.WriteLine(RoundAndFormat(1));
Console.WriteLine(RoundAndFormat(10));
Console.WriteLine(RoundAndFormat(100));
Console.WriteLine(RoundAndFormat(1000));
Console.WriteLine(RoundAndFormat(100000));
Console.WriteLine(RoundAndFormat(125000));
Console.WriteLine(RoundAndFormat(125900));
Console.WriteLine(RoundAndFormat(1000000));
Console.WriteLine(RoundAndFormat(1250000));
Console.WriteLine(RoundAndFormat(1258000));
Console.WriteLine(RoundAndFormat(10000000));
Console.WriteLine(RoundAndFormat(10500000));
Console.WriteLine(RoundAndFormat(100000000));
Console.WriteLine(RoundAndFormat(100100000));
Console.ReadLine();
}
public static String RoundAndFormat(Int32 value)
{
var result = String.Empty;
var negative = value < 0;
if (negative) value = value * -1;
if (value < 1000)
{
result = value.ToString();
}
else if (value < 1000000)
{
result = RoundDown(value / 1000.0, 0) + "K";
}
else if (value < 100000000)
{
result = RoundDown(value / 1000000.0, 2) + "M";
}
else if (value < 10000000000)
{
result = RoundDown(value / 1000000.0, 0) + "M";
}
if (negative) return "-" + result;
return result;
}
public static Double RoundDown(Double value, Int32 digits)
{
var pow = Math.Pow(10, digits);
return Math.Truncate(value * pow) / pow;
}
这是我的带有测试输出的代码
1249 1.24K
12499 12.4K
124999 124K
1249999 1.24M
12499999 12.4M
124999999 124M
1249999999 1.24B
代码最多输出三位数字。
static string FormatNumber(uint n)
{
if (n < 1000)
return n.ToString();
if (n < 10000)
return String.Format("{0:#,.##}K", n - 5);
if (n < 100000)
return String.Format("{0:#,.#}K", n - 50);
if (n < 1000000)
return String.Format("{0:#,.}K", n - 500);
if (n < 10000000)
return String.Format("{0:#,,.##}M", n - 5000);
if (n < 100000000)
return String.Format("{0:#,,.#}M", n - 50000);
if (n < 1000000000)
return String.Format("{0:#,,.}M", n - 500000);
return String.Format("{0:#,,,.##}B", n - 5000000);
}
感谢大家的帮助,这让我走上了正确的道路,自己解决了这个问题。
public static string FormatPriceValue(this int num)
{
if (num >= 100000000)
{
return ((num >= 10050000 ? num - 500000 : num) / 1000000D).ToString("#M");
}
if (num >= 10000000)
{
return ((num >= 10500000 ? num - 50000 : num) / 1000000D).ToString("0.#M");
}
if (num >= 1000000)
{
return ((num >= 1005000 ? num-5000 : num) / 1000000D).ToString("0.##M");
}
if (num >= 100000)
{
return ((num >= 100500 ? num - 500 : num) / 1000D).ToString("0.k");
}
if (num >= 10000)
{
return ((num >= 10550 ? num - 50 : num) / 1000D).ToString("0.#k");
}
return num >= 1000 ? ((num >= 1005 ? num - 5 : num) / 1000D).ToString("0.##k") : num.ToString("#,0");
}
我知道这是一个老问题,但我不禁注意到这些答案中的大部分都无法扩展,其中大部分都是为获得更多值而重复的非常相似的代码行。我需要一些对更大价值起作用的东西,所以我尝试以一种聪明的方式使用数学而不是重复的代码。这确实需要使用浮点数学(双精度),因为无符号长整型的最大值仅为 1.84e+19。我的解决方案:
public static string GetStringRepresentation(double count)
{
string tokens = " KMBtqQsSondUDT"; //Infinitely expandable (at least to the limit of double floating point values)
for (double i = 1; true; i += 1)
{
double val = Math.Pow(1000, i);
if (val > count)
{
return $"{count / Math.Pow(1000, i - 1)}{tokens[(int)i - 1]}".Trim();
}
}
}
测试代码:
Console.WriteLine(" 1: " + GetStringRepresentation( 1).PadLeft(7, ' '));
Console.WriteLine(" 12: " + GetStringRepresentation( 12).PadLeft(7, ' '));
Console.WriteLine(" 123: " + GetStringRepresentation( 123).PadLeft(7, ' '));
Console.WriteLine(" 1230: " + GetStringRepresentation( 1230).PadLeft(7, ' '));
Console.WriteLine(" 12340: " + GetStringRepresentation( 12340).PadLeft(7, ' '));
Console.WriteLine(" 123450: " + GetStringRepresentation( 123450).PadLeft(7, ' '));
Console.WriteLine(" 1230000: " + GetStringRepresentation( 1230000).PadLeft(7, ' '));
Console.WriteLine(" 12340000: " + GetStringRepresentation( 12340000).PadLeft(7, ' '));
Console.WriteLine(" 123450000: " + GetStringRepresentation( 123450000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000: " + GetStringRepresentation( 1230000000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000000: " + GetStringRepresentation( 1230000000000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000000000: " + GetStringRepresentation( 1230000000000000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000000000000: " + GetStringRepresentation(1230000000000000000).PadLeft(7, ' '));
输出:
1: 1
12: 12
123: 123
1230: 1,23K
12340: 12,34K
123450: 123,45K
1230000: 1,23M
12340000: 12,34M
123450000: 123,45M
1230000000: 1,23B
1230000000000: 1,23t
1230000000000000: 1,23q
1230000000000000000: 1,23Q
下面是一个 VBS/VbScript 函数来执行此操作。
注意 => VB 和 VB提供直接格式调用。
' 用法:Return 一个数字使用它的千位符号(例如:234,789,145 = 234.8M)
函数Format_Large_Number(nb, nbDigit)
' Safety
If Not IsNumeric(nb) Then FormatLargeNumber = nb : Exit Function
If nbDigit < 1 Then nbDigit = 1
If nbDigit > 3 Then nbDigit = 3
' Initiate var
Dim rtnNb : rtnNb = nb
Dim nbFormat : nbFormat = FormatCurrency(rtnNb, 0, vbTrue, vbTrue)
nbFormat = Trim(Replace(nbFormat, "$", ""))
Dim nbSymbol : nbSymbol = ""
Dim nbDecRnd : nbDecRnd = ""
Dim arrNb : arrNb = Split(nbFormat, " ")
' Asign symbol
Select Case UBound(arrNb)
Case 0
nbSymbol = "" ' Hundred
Case 1
nbSymbol = "K" ' Thousand
Case 2
nbSymbol = "M" ' Million
Case 3
nbSymbol = "G" ' Billion
Case 4
nbSymbol = "T" ' Trillion
Case 5
nbSymbol = "P" ' Quadrillion
Case 6
nbSymbol = "E" ' Quintillion
End Select
' Concatenate rtn string
If Ubound(arrNb) > 0 Then
If nbDigit < 3 Then
If CInt(arrNb(1)) > 499 Then
nbDecRnd = CStr(CInt(Left(arrNb(1),nbDigit)) + 1) ' Ceil decimal rtn
Else
nbDecRnd = Left(arrNb(1),nbDigit)
End If
Else
nbDecRnd = Left(arrNb(1),nbDigit)
End If
rtnNb = arrNb(0) & "," & nbDecRnd & nbSymbol ' All others
Else
rtnNb = arrNb(0) & nbSymbol ' Hundred
End If
' Rtn value
Format_Large_Number = rtnNb
结束函数
我正在尝试设置显示价格的格式,我想显示一个带有百万 (M) 或千 (K) 后缀的数字,但最多只显示 3 个向下舍入的值。
我发现 this question 非常接近我想要的,但不处理舍入(具体来说,总是向下舍入)
同样,with this question 您无法控制舍入。
示例 input/expected 输出:
1 = 1
10 = 10
100 = 100
1000 = 1K
100000 = 100K
125000 = 125K
125900 = 125K
1000000 = 1M
1250000 = 1.25M
1258000 = 1.25M
10000000 = 10M
10500000 = 10.5M
100000000 = 100M
100100000 = 100M
我基本上只想显示 3 个值。
我看不出如何使用 "," custom specifier 和指定舍入。
我最初的想法是我需要结合使用上述方法,Math.Floor 和一些 .ToString() 格式化魔法,但我不确定从哪里开始。
有人可以帮我吗?
提前致谢。
结合您链接到的其他问题中的一种格式化技术,这应该会有所帮助。
internal long MaxThreeSignificantDigits(long x)
{
int i = (int)Math.Log10(x);
i = Math.Max(0, i - 2);
i = (int)Math.Pow(10, i);
return x / i * i;
}
编辑:
好的,这个怎么样?
Console.WriteLine(SO30180672.FormatNumber(1));
Console.WriteLine(SO30180672.FormatNumber(12));
Console.WriteLine(SO30180672.FormatNumber(123));
Console.WriteLine(SO30180672.FormatNumber(1234));
Console.WriteLine(SO30180672.FormatNumber(12345));
Console.WriteLine(SO30180672.FormatNumber(123456));
Console.WriteLine(SO30180672.FormatNumber(1234567));
Console.WriteLine(SO30180672.FormatNumber(12345678));
Console.WriteLine(SO30180672.FormatNumber(123456789));
以下是从此处复制的部分内容:
internal class SO30180672
{
internal static string FormatNumber(long num)
{
num = MaxThreeSignificantDigits(num);
if (num >= 100000000)
return (num / 1000000D).ToString("0.#M");
if (num >= 1000000)
return (num / 1000000D).ToString("0.##M");
if (num >= 100000)
return (num / 1000D).ToString("0k");
if (num >= 100000)
return (num / 1000D).ToString("0.#k");
if (num >= 1000)
return (num / 1000D).ToString("0.##k");
return num.ToString("#,0");
}
internal static long MaxThreeSignificantDigits(long x)
{
int i = (int)Math.Log10(x);
i = Math.Max(0, i - 2);
i = (int)Math.Pow(10, i);
return x / i * i;
}
}
编辑 2 - 非常感谢@Rhexis
internal class SO30180672
{
internal static void RunTest()
{
Console.WriteLine(FormatNumber(1));
Console.WriteLine(FormatNumber(10));
Console.WriteLine(FormatNumber(100));
Console.WriteLine(FormatNumber(1000));
Console.WriteLine(FormatNumber(10000));
Console.WriteLine(FormatNumber(100000));
Console.WriteLine(FormatNumber(125000));
Console.WriteLine(FormatNumber(125900));
Console.WriteLine(FormatNumber(1000000));
Console.WriteLine(FormatNumber(1250000));
Console.WriteLine(FormatNumber(1258000));
Console.WriteLine(FormatNumber(10000000));
Console.WriteLine(FormatNumber(10500000));
Console.WriteLine(FormatNumber(100000000));
Console.WriteLine(FormatNumber(100100000));
}
private static string FormatNumber(long num)
{
// Ensure number has max 3 significant digits (no rounding up can happen)
long i = (long)Math.Pow(10, (int)Math.Max(0, Math.Log10(num) - 2));
num = num / i * i;
if (num >= 1000000000)
return (num / 1000000000D).ToString("0.##") + "B";
if (num >= 1000000)
return (num / 1000000D).ToString("0.##") + "M";
if (num >= 1000)
return (num / 1000D).ToString("0.##") + "K";
return num.ToString("#,0");
}
}
由于格式本质上会根据范围发生变化,因此您很可能需要类似于下面的一些条件格式。我只测试了提供的样本集,因此请确保它适用于所有预期值范围。
class Program
{
static void Main(String[] args)
{
Console.WriteLine(RoundAndFormat(1));
Console.WriteLine(RoundAndFormat(10));
Console.WriteLine(RoundAndFormat(100));
Console.WriteLine(RoundAndFormat(1000));
Console.WriteLine(RoundAndFormat(100000));
Console.WriteLine(RoundAndFormat(125000));
Console.WriteLine(RoundAndFormat(125900));
Console.WriteLine(RoundAndFormat(1000000));
Console.WriteLine(RoundAndFormat(1250000));
Console.WriteLine(RoundAndFormat(1258000));
Console.WriteLine(RoundAndFormat(10000000));
Console.WriteLine(RoundAndFormat(10500000));
Console.WriteLine(RoundAndFormat(100000000));
Console.WriteLine(RoundAndFormat(100100000));
Console.ReadLine();
}
public static String RoundAndFormat(Int32 value)
{
var result = String.Empty;
var negative = value < 0;
if (negative) value = value * -1;
if (value < 1000)
{
result = value.ToString();
}
else if (value < 1000000)
{
result = RoundDown(value / 1000.0, 0) + "K";
}
else if (value < 100000000)
{
result = RoundDown(value / 1000000.0, 2) + "M";
}
else if (value < 10000000000)
{
result = RoundDown(value / 1000000.0, 0) + "M";
}
if (negative) return "-" + result;
return result;
}
public static Double RoundDown(Double value, Int32 digits)
{
var pow = Math.Pow(10, digits);
return Math.Truncate(value * pow) / pow;
}
这是我的带有测试输出的代码
1249 1.24K
12499 12.4K
124999 124K
1249999 1.24M
12499999 12.4M
124999999 124M
1249999999 1.24B
代码最多输出三位数字。
static string FormatNumber(uint n)
{
if (n < 1000)
return n.ToString();
if (n < 10000)
return String.Format("{0:#,.##}K", n - 5);
if (n < 100000)
return String.Format("{0:#,.#}K", n - 50);
if (n < 1000000)
return String.Format("{0:#,.}K", n - 500);
if (n < 10000000)
return String.Format("{0:#,,.##}M", n - 5000);
if (n < 100000000)
return String.Format("{0:#,,.#}M", n - 50000);
if (n < 1000000000)
return String.Format("{0:#,,.}M", n - 500000);
return String.Format("{0:#,,,.##}B", n - 5000000);
}
感谢大家的帮助,这让我走上了正确的道路,自己解决了这个问题。
public static string FormatPriceValue(this int num)
{
if (num >= 100000000)
{
return ((num >= 10050000 ? num - 500000 : num) / 1000000D).ToString("#M");
}
if (num >= 10000000)
{
return ((num >= 10500000 ? num - 50000 : num) / 1000000D).ToString("0.#M");
}
if (num >= 1000000)
{
return ((num >= 1005000 ? num-5000 : num) / 1000000D).ToString("0.##M");
}
if (num >= 100000)
{
return ((num >= 100500 ? num - 500 : num) / 1000D).ToString("0.k");
}
if (num >= 10000)
{
return ((num >= 10550 ? num - 50 : num) / 1000D).ToString("0.#k");
}
return num >= 1000 ? ((num >= 1005 ? num - 5 : num) / 1000D).ToString("0.##k") : num.ToString("#,0");
}
我知道这是一个老问题,但我不禁注意到这些答案中的大部分都无法扩展,其中大部分都是为获得更多值而重复的非常相似的代码行。我需要一些对更大价值起作用的东西,所以我尝试以一种聪明的方式使用数学而不是重复的代码。这确实需要使用浮点数学(双精度),因为无符号长整型的最大值仅为 1.84e+19。我的解决方案:
public static string GetStringRepresentation(double count)
{
string tokens = " KMBtqQsSondUDT"; //Infinitely expandable (at least to the limit of double floating point values)
for (double i = 1; true; i += 1)
{
double val = Math.Pow(1000, i);
if (val > count)
{
return $"{count / Math.Pow(1000, i - 1)}{tokens[(int)i - 1]}".Trim();
}
}
}
测试代码:
Console.WriteLine(" 1: " + GetStringRepresentation( 1).PadLeft(7, ' '));
Console.WriteLine(" 12: " + GetStringRepresentation( 12).PadLeft(7, ' '));
Console.WriteLine(" 123: " + GetStringRepresentation( 123).PadLeft(7, ' '));
Console.WriteLine(" 1230: " + GetStringRepresentation( 1230).PadLeft(7, ' '));
Console.WriteLine(" 12340: " + GetStringRepresentation( 12340).PadLeft(7, ' '));
Console.WriteLine(" 123450: " + GetStringRepresentation( 123450).PadLeft(7, ' '));
Console.WriteLine(" 1230000: " + GetStringRepresentation( 1230000).PadLeft(7, ' '));
Console.WriteLine(" 12340000: " + GetStringRepresentation( 12340000).PadLeft(7, ' '));
Console.WriteLine(" 123450000: " + GetStringRepresentation( 123450000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000: " + GetStringRepresentation( 1230000000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000000: " + GetStringRepresentation( 1230000000000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000000000: " + GetStringRepresentation( 1230000000000000).PadLeft(7, ' '));
Console.WriteLine(" 1230000000000000000: " + GetStringRepresentation(1230000000000000000).PadLeft(7, ' '));
输出:
1: 1
12: 12
123: 123
1230: 1,23K
12340: 12,34K
123450: 123,45K
1230000: 1,23M
12340000: 12,34M
123450000: 123,45M
1230000000: 1,23B
1230000000000: 1,23t
1230000000000000: 1,23q
1230000000000000000: 1,23Q
下面是一个 VBS/VbScript 函数来执行此操作。 注意 => VB 和 VB提供直接格式调用。
' 用法:Return 一个数字使用它的千位符号(例如:234,789,145 = 234.8M)
函数Format_Large_Number(nb, nbDigit)
' Safety
If Not IsNumeric(nb) Then FormatLargeNumber = nb : Exit Function
If nbDigit < 1 Then nbDigit = 1
If nbDigit > 3 Then nbDigit = 3
' Initiate var
Dim rtnNb : rtnNb = nb
Dim nbFormat : nbFormat = FormatCurrency(rtnNb, 0, vbTrue, vbTrue)
nbFormat = Trim(Replace(nbFormat, "$", ""))
Dim nbSymbol : nbSymbol = ""
Dim nbDecRnd : nbDecRnd = ""
Dim arrNb : arrNb = Split(nbFormat, " ")
' Asign symbol
Select Case UBound(arrNb)
Case 0
nbSymbol = "" ' Hundred
Case 1
nbSymbol = "K" ' Thousand
Case 2
nbSymbol = "M" ' Million
Case 3
nbSymbol = "G" ' Billion
Case 4
nbSymbol = "T" ' Trillion
Case 5
nbSymbol = "P" ' Quadrillion
Case 6
nbSymbol = "E" ' Quintillion
End Select
' Concatenate rtn string
If Ubound(arrNb) > 0 Then
If nbDigit < 3 Then
If CInt(arrNb(1)) > 499 Then
nbDecRnd = CStr(CInt(Left(arrNb(1),nbDigit)) + 1) ' Ceil decimal rtn
Else
nbDecRnd = Left(arrNb(1),nbDigit)
End If
Else
nbDecRnd = Left(arrNb(1),nbDigit)
End If
rtnNb = arrNb(0) & "," & nbDecRnd & nbSymbol ' All others
Else
rtnNb = arrNb(0) & nbSymbol ' Hundred
End If
' Rtn value
Format_Large_Number = rtnNb
结束函数