格式数字如堆栈溢出(四舍五入成千上万的K后缀)
如何格式化数字像SO与C#?
10,5k,…
像这样:( 编辑 :testing)
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"); }
例子:
- 1 =>
1
- 23 =>
23
- 136 =>
136
- 6968 =>
6,968
- 23067 =>
23.1K
- 133031 =>
133K
请注意,这会给数字> = 10 8的奇怪值。
例如, 12345678
变成12.3KK
。
你可以像这样创build一个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(); } }
像这样使用它:
String.Format(new KiloFormatter(), "{0:K}", 15600);
编辑 :将CurrencyFormatter更名为KiloFormatter
下面的代码被testing到int.MaxValue这不是最美丽的代码,但是是最有效的。 但是你可以使用它:
123.KiloFormat(); 4332.KiloFormat(); 2332124.KiloFormat(); int.MaxValue.KiloFormat(); (int1 – int2 * int3).KiloFormat();
等等…
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"); } }
我只是写了一些提供完整的信息
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 }; } }
使用:
var amountInfo = SIPrefix.GetInfo(10250, 2); var amountInfo2 = SIPrefix.GetInfo(2500000, 0); amountInfo.AmountWithPrefix // 10.25K amountInfo2.AmountWithPrefix // 2M
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"); }
这将返回以下值:
123 -> 123 1234 -> 1,234 12345 -> 12.35k 123456 -> 123.4k 1234567 -> 1.23M 12345678 -> 12.35M 123456789 -> 123.5M
我写了这个方法来缩小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"); }
像这样的东西:
string formatted; if (num >= 1000) { formatted = ((double)num / 1000.0).ToString("N1") + "k"; } else { formatted = num.ToString("N0"); }
如果数字大于某个阈值,则将其除以1000,然后将其格式化为所需的许多小数位数。
int input = 12392; // for example if (input >= 10000) { double thousands = input/1000.0; Console.WriteLine(string.Format("{0}K", thousands)); }
我知道这是一个非常古老的线索,但我认为更通用的答案可能是有用的:
ADD:忽略它应该是C#,所以在这里它被翻译成:
//--Formats the number after scaling by factors of 1000, and appends a metric unit prefix (eg 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)); }
这是用于SQL的:
--Formats the number after scaling by factors of 1000, and appends a metric unit prefix (eg 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
然后也许一些相关的包装function,以减轻使用,例如
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
和一堆testing/例子:
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)
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()); }