C# 像 Stack Overflow 一样的格式编号(四舍五入到千,后缀为 K)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2134161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Format Number like Stack Overflow (rounded to thousands with K suffix)
提问by Yoann. B
How to format numbers like SO with C#?
如何使用 C# 格式化像 SO 这样的数字?
10, 5k, ...
10, 5k, ...
采纳答案by SLaks
Like this: (EDIT: Tested)
像这样:(编辑:测试)
static string FormatNumber(int num) {
if (num >= 100000)
return FormatNumber(num / 1000) + "K";
if (num >= 10000) {
return (num / 1000D).ToString("0.#") + "K";
}
return num.ToString("#,0");
}
Examples:
例子:
- 1 =>
1
- 23 =>
23
- 136 =>
136
- 6968 =>
6,968
- 23067 =>
23.1K
- 133031 =>
133K
- 1 =>
1
- 23 =>
23
- 136 =>
136
- 6968 =>
6,968
- 23067 =>
23.1K
- 133031 =>
133K
Note that this will give strange values for numbers >= 108.
For example, 12345678
becomes 12.3KK
.
请注意,这将为数字 >= 10 8提供奇怪的值。
例如,12345678
变成12.3KK
。
回答by Guffa
Something like this:
像这样的东西:
string formatted;
if (num >= 1000) {
formatted = ((double)num / 1000.0).ToString("N1") + "k";
} else {
formatted = num.ToString("N0");
}
回答by Daniel Earwicker
If the number is bigger than some threshold, divide it by 1000 and then format it to however many decimal places you need.
如果数字大于某个阈值,请将其除以 1000,然后将其格式化为您需要的小数位数。
int input = 12392; // for example
if (input >= 10000)
{
double thousands = input/1000.0;
Console.WriteLine(string.Format("{0}K", thousands));
}
回答by Alex LE
You can crate a CustomFormater like this:
您可以像这样创建 CustomFormater:
public class KiloFormatter: ICustomFormatter, IFormatProvider
{
public object GetFormat(Type formatType)
{
return (formatType == typeof(ICustomFormatter)) ? this : null;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
if (format == null || !format.Trim().StartsWith("K")) {
if (arg is IFormattable) {
return ((IFormattable)arg).ToString(format, formatProvider);
}
return arg.ToString();
}
decimal value = Convert.ToDecimal(arg);
// Here's is where you format your number
if (value > 1000) {
return (value / 1000).ToString() + "k";
}
return value.ToString();
}
}
And use it like this:
并像这样使用它:
String.Format(new KiloFormatter(), "{0:K}", 15600);
edit: Renamed CurrencyFormatter to KiloFormatter
编辑:将 CurrencyFormatter 重命名为 KiloFormatter
回答by Alex LE
The code below is tested up to int.MaxValue This is not the most beautiful code but is most efficient. But you can use it as:
下面的代码测试到 int.MaxValue 这不是最漂亮的代码,但最有效。但是您可以将其用作:
123.KiloFormat(); 4332.KiloFormat(); 2332124.KiloFormat(); int.MaxValue.KiloFormat(); (int1 - int2 * int3).KiloFormat();
123.KiloFormat(); 4332.KiloFormat(); 2332124.KiloFormat(); int.MaxValue.KiloFormat(); (int1 - int2 * int3).KiloFormat();
etc...
等等...
public static class Extensions
{
public static string KiloFormat(this int num)
{
if (num >= 100000000)
return (num / 1000000).ToString("#,0M");
if (num >= 10000000)
return (num / 1000000).ToString("0.#") + "M";
if (num >= 100000)
return (num / 1000).ToString("#,0K");
if (num >= 10000)
return (num / 1000).ToString("0.#") + "K";
return num.ToString("#,0");
}
}
回答by Cruiser KID
I just wrote some to provide complete information
我只是写了一些来提供完整的信息
public static class SIPrefix
{
private static List<SIPrefixInfo> _SIPrefixInfoList = new
List<SIPrefixInfo>();
static SIPrefix()
{
_SIPrefixInfoList = new List<SIPrefixInfo>();
LoadSIPrefix();
}
public static List<SIPrefixInfo> SIPrefixInfoList
{
get
{
SIPrefixInfo[] siPrefixInfoList = new SIPrefixInfo[6];
_SIPrefixInfoList.CopyTo(siPrefixInfoList);
return siPrefixInfoList.ToList();
}
}
private static void LoadSIPrefix()
{
_SIPrefixInfoList.AddRange(new SIPrefixInfo[]{
new SIPrefixInfo() {Symbol = "Y", Prefix = "yotta", Example = 1000000000000000000000000.00M, ZeroLength = 24, ShortScaleName = "Septillion", LongScaleName = "Quadrillion"},
new SIPrefixInfo() {Symbol = "Z", Prefix = "zetta", Example = 1000000000000000000000M, ZeroLength = 21, ShortScaleName = "Sextillion", LongScaleName = "Trilliard"},
new SIPrefixInfo() {Symbol = "E", Prefix = "exa", Example = 1000000000000000000M, ZeroLength = 18, ShortScaleName = "Quintillion", LongScaleName = "Trillion"},
new SIPrefixInfo() {Symbol = "P", Prefix = "peta", Example = 1000000000000000M, ZeroLength = 15, ShortScaleName = "Quadrillion", LongScaleName = "Billiard"},
new SIPrefixInfo() {Symbol = "T", Prefix = "tera", Example = 1000000000000M, ZeroLength = 12, ShortScaleName = "Trillion", LongScaleName = "Billion"},
new SIPrefixInfo() {Symbol = "G", Prefix = "giga", Example = 1000000000M, ZeroLength = 9, ShortScaleName = "Billion", LongScaleName = "Milliard"},
new SIPrefixInfo() {Symbol = "M", Prefix = "mega", Example = 1000000M, ZeroLength = 6, ShortScaleName = "Million", LongScaleName = "Million"},
new SIPrefixInfo() {Symbol = "K", Prefix = "kilo", Example = 1000M, ZeroLength = 3, ShortScaleName = "Thousand", LongScaleName = "Thousand"},
new SIPrefixInfo() {Symbol = "h", Prefix = "hecto", Example = 100M, ZeroLength = 2, ShortScaleName = "Hundred", LongScaleName = "Hundred"},
new SIPrefixInfo() {Symbol = "da", Prefix = "deca", Example = 10M, ZeroLength = 1, ShortScaleName = "Ten", LongScaleName = "Ten"},
new SIPrefixInfo() {Symbol = "", Prefix = "", Example = 1M, ZeroLength = 0, ShortScaleName = "One", LongScaleName = "One"},
});
}
public static SIPrefixInfo GetInfo(long amount, int decimals)
{
return GetInfo(Convert.ToDecimal(amount), decimals);
}
public static SIPrefixInfo GetInfo(decimal amount, int decimals)
{
SIPrefixInfo siPrefixInfo = null;
decimal amountToTest = Math.Abs(amount);
var amountLength = amountToTest.ToString("0").Length;
if(amountLength < 3)
{
siPrefixInfo = _SIPrefixInfoList.Find(i => i.ZeroLength == amountLength).Clone() as SIPrefixInfo;
siPrefixInfo.AmountWithPrefix = Math.Round(amount, decimals).ToString();
return siPrefixInfo;
}
siPrefixInfo = _SIPrefixInfoList.Find(i => amountToTest > i.Example).Clone() as SIPrefixInfo;
siPrefixInfo.AmountWithPrefix = Math.Round(
amountToTest / Convert.ToDecimal(siPrefixInfo.Example), decimals).ToString()
+ siPrefixInfo.Symbol;
return siPrefixInfo;
}
}
public class SIPrefixInfo : ICloneable
{
public string Symbol { get; set; }
public decimal Example { get; set; }
public string Prefix { get; set; }
public int ZeroLength { get; set; }
public string ShortScaleName { get; set; }
public string LongScaleName { get; set; }
public string AmountWithPrefix { get; set; }
public object Clone()
{
return new SIPrefixInfo()
{
Example = this.Example,
LongScaleName = this.LongScaleName,
ShortScaleName = this.ShortScaleName,
Symbol = this.Symbol,
Prefix = this.Prefix,
ZeroLength = this.ZeroLength
};
}
}
Use:
用:
var amountInfo = SIPrefix.GetInfo(10250, 2);
var amountInfo2 = SIPrefix.GetInfo(2500000, 0);
amountInfo.AmountWithPrefix // 10.25K
amountInfo2.AmountWithPrefix // 2M
回答by Majid
I wrote this method to minify long
numbers:
我写了这个方法来缩小long
数字:
public string minifyLong(long value)
{
if (value >= 100000000000)
return (value / 1000000000).ToString("#,0") + " B";
if (value >= 10000000000)
return (value / 1000000000D).ToString("0.#") + " B";
if (value >= 100000000)
return (value / 1000000).ToString("#,0") + " M";
if (value >= 10000000)
return (value / 1000000D).ToString("0.#") + " M";
if (value >= 100000)
return (value / 1000).ToString("#,0") + " K";
if (value >= 10000)
return (value / 1000D).ToString("0.#") + " K";
return value.ToString("#,0");
}
回答by hex
A slightly modified version of SLaks code
SLaks 代码的稍微修改版本
static string FormatNumber(long 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("0.#k");
}
if (num >= 10000) {
return (num / 1000D).ToString("0.##k");
}
return num.ToString("#,0");
}
This will return the following values:
这将返回以下值:
123 -> 123
1234 -> 1,234
12345 -> 12.35k
123456 -> 123.4k
1234567 -> 1.23M
12345678 -> 12.35M
123456789 -> 123.5M
回答by Eske Rahn
I know this is a very old thread, but I think a more generic answer could be useful:
我知道这是一个非常古老的线程,但我认为更通用的答案可能有用:
ADD: overlooked that it should have been C#, so here it is translated:
ADD:忽略它应该是C#,所以在这里翻译:
//--Formats the number after scaling by factors of 1000, and appends a metric unit prefix (e.g. M for *1000000)
//--Mask, Prov are the standard ToString() parameters (after metric scaling has been performed)
//--MinPow10 (/Max) should be multipla of 3 and a usually a negative (/Positve) number or zero, if say +9 is used, all is in G or above (/below)
//--SwitchLimit usualy 1, but could be say 10 or 100 with few/zero decimals, The limit at which to switch prefix, if say 33 then 33000000->33M but 32900000->32900K
static string FormatMetricPrefix(double Input, String Mask ="F2", IFormatProvider Prov=null, int MinPow10 =-24, int MaxPow10 =24, int SwitchLimit =1) {
string Prefixes ="yzafpnμm KMGTPEZY";
int idx=9;
double tmp=Input;
if (Input!=0.0) {
if (+24<MaxPow10)MaxPow10=+24;
if (MinPow10<-24)MaxPow10=-24;
idx=(int)Math.Truncate(9.0+Math.Log(Math.Abs(Input/SwitchLimit))/Math.Log(1000.0));
if (idx<9+(MinPow10/3)) idx=9+(MinPow10/3); // below lower limit
if (9+(MaxPow10/3)<idx) idx=9+(MaxPow10/3); // Above upper limit
if (idx<=9)tmp *=Math.Pow(1000.0,9-idx);
if (9<idx) tmp /=Math.Pow(1000.0,idx-9);
}
if (Prov==null)Prov=CultureInfo.InvariantCulture;
return tmp.ToString(Mask,Prov)+Prefixes.Substring(idx-1,1).Trim();
}
static string FormatMetricPrefixF2DK(double Input){return FormatMetricPrefix(Input, Prov:CultureInfo.GetCultureInfo("da-DK"));}
static string FormatMetricPrefixF2US(double Input){return FormatMetricPrefix(Input, Prov:CultureInfo.GetCultureInfo("en-US"));}
static string FormatMetricPrefixF0DK(double Input){return FormatMetricPrefix(Input, Mask:"F0", MinPow10:0, Prov:CultureInfo.GetCultureInfo("da-DK"),SwitchLimit:100);}
static string FormatMetricPrefixF0US(double Input){return FormatMetricPrefix(Input, Mask:"F0", MinPow10:0, Prov:CultureInfo.GetCultureInfo("en-US"),SwitchLimit:100);}
static void Main(string[] args)
{
Console.WriteLine(FormatMetricPrefixF2US(1.234567890E+27));
Console.WriteLine(FormatMetricPrefixF2US(1234567890));
Console.WriteLine(FormatMetricPrefixF2US(0.01234567890));
Console.WriteLine(FormatMetricPrefixF2US(0.00000001234567890));
Console.WriteLine(FormatMetricPrefixF2US(1.234567890E-26));
Console.WriteLine(FormatMetricPrefixF0US(0.5));
Console.WriteLine(FormatMetricPrefixF0US(2));
Console.WriteLine(FormatMetricPrefixF0US(20000));
Console.WriteLine(FormatMetricPrefixF0US(87654321));
}
And this is for SQL:
这是针对 SQL:
--Formats the number after scaling by factors of 1000, and appends a metric unit prefix (e.g. M for *1000000)
--@Mask, @Cult are the standard FORMAT parameters (after metric scaling has been performed)
--@MinPow10 (/Max) should be multipla of 3 and a usually a negative (/Positve) number or zero, if say +9 is used, all is in G or above (/below)
--@SwitchLimit usualy 1, but could be say 10 or 100 with few/zero decimals, The limit at which to switch prefix, if say 33 then 33000000->33M but 32900000->32900K
CREATE function FormatMetricPrefix(@Input float, @Mask Varchar(22)='F2', @Cult Varchar(9)='en-us', @MinPow10 int =-24, @MaxPow10 int =24, @SwitchLimit int=1) returns Varchar(99) as
Begin
Declare @Prefixes Varchar(17)='yzafpnμm KMGTPEZY'
Declare @idx int = 9
Declare @tmp float=@input
if @Input<>0.0
begin
if +24<@MaxPow10 set @MaxPow10=+24 --highest limit is y 10^24
if @MinPow10<-24 set @MinPow10=-24 --lowest limit is y 10^-24
set @idx=9.0+Log(Abs(@input/@SwitchLimit))/Log(1000)
If @idx<9+(@MinPow10/3) set @idx=9+(@MinPow10/3) -- below lower limit
If 9+(@MaxPow10/3)<@idx set @idx=9+(@MaxPow10/3) --above upper limit
if @idx<=9set @tmp=@tmp*POWER(1000.0,9-@idx)
if 9<@idx set @tmp=@tmp/POWER(1000.0,@idx-9)
end
Return FORMAT(@tmp,@mask,@Cult)+LTrim(Substring(@Prefixes,@idx,1))
end
GO
And then perhaps some relevant wrapper functions to ease the use, e.g.
然后也许是一些相关的包装函数来简化使用,例如
CREATE function FormatMetricPrefixF2US(@Input float) returns Varchar(99) as
begin
return dbo.FormatMetricPrefix(@Input, default,default,default,default,default)
end
GO
CREATE function FormatMetricPrefixF0US(@Input float) returns Varchar(99) as
begin
return dbo.FormatMetricPrefix(@Input, 'F0' ,default, 0 ,default, 100 )
end
GO
And a bunch of test/examples:
还有一堆测试/示例:
Select 0, dbo.FormatMetricPrefixF2US(1.234567890E+27)+'g'
union Select 1, dbo.FormatMetricPrefixF2US(1234567890)+'g'
union Select 2, dbo.FormatMetricPrefixF2US(123456789.0)+'g'
union Select 3, dbo.FormatMetricPrefixF2US(12345678.90)+'g'
union Select 4, dbo.FormatMetricPrefixF2US(1234567.890)+'g'
union Select 5, dbo.FormatMetricPrefixF2US(123456.7890)+'g'
union Select 6, dbo.FormatMetricPrefixF2US(12345.67890)+'g'
union Select 7, dbo.FormatMetricPrefixF2US(1234.567890)+'g'
union Select 8, dbo.FormatMetricPrefixF2US(123.4567890)+'g'
union Select 9, dbo.FormatMetricPrefixF2US(12.34567890)+'g'
union Select 10, dbo.FormatMetricPrefixF2US(1.234567890)+'g'
union Select 11, dbo.FormatMetricPrefixF2US(0.1234567890)+'g'
union Select 12, dbo.FormatMetricPrefixF2US(0.01234567890)+'g'
union Select 13, dbo.FormatMetricPrefixF2US(0.001234567890)+'g'
union Select 14, dbo.FormatMetricPrefixF2US(0.0001234567890)+'g'
union Select 15, dbo.FormatMetricPrefixF2US(0.00001234567890)+'g'
union Select 16, dbo.FormatMetricPrefixF2US(0.000001234567890)+'g'
union Select 17, dbo.FormatMetricPrefixF2US(0.0000001234567890)+'g'
union Select 18, dbo.FormatMetricPrefixF2US(0.00000001234567890)+'g'
union Select 19, dbo.FormatMetricPrefixF2US(1.234567890E-26)+'g'
union Select 20, dbo.FormatMetricPrefixF0US(0.5)
union Select 20, dbo.FormatMetricPrefixF0US(2)
union Select 21, dbo.FormatMetricPrefixF0US(20000)
union Select 22, dbo.FormatMetricPrefixF0US(87654321)
回答by xleon
public static class NumberDisplayHelper
{
public static string KiloFormat(this decimal number)
{
return number >= 1000
? $"{(number / 1000):0.##}K"
: number.ToString(CultureInfo.CurrentCulture);
}
public static string KiloFormat(this int number)
{
return number >= 1000
? $"{((decimal)number / 1000):0.##}K"
: number.ToString();
}
}
[Test()]
public void KiloFormatter()
{
Assert.AreEqual("900", 900m.KiloFormat());
Assert.AreEqual("1,2K", 1203m.KiloFormat());
Assert.AreEqual("1,59K", 1588.84m.KiloFormat());
Assert.AreEqual("1,52K", 1522.84m.KiloFormat());
Assert.AreEqual("589", 589.KiloFormat());
Assert.AreEqual("1K", 1001.KiloFormat());
Assert.AreEqual("1,46K", 1455.KiloFormat());
Assert.AreEqual("1K", 1000m.KiloFormat());
}