Làm cách nào để định dạng các số như SO với C#?Định dạng Số như Stack Overflow (được làm tròn đến hàng nghìn với hậu tố K)
10, 5k, ...
Làm cách nào để định dạng các số như SO với C#?Định dạng Số như Stack Overflow (được làm tròn đến hàng nghìn với hậu tố K)
10, 5k, ...
Như thế này: (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");
}
Ví dụ:
1
23
136
6,968
23.1K
133K
Lưu ý rằng điều này sẽ cung cấp cho các giá trị xa lạ đối với số> = 10 .
Ví dụ: 12345678
trở thành 12.3KK
.
Something như thế này:
string formatted;
if (num >= 1000) {
formatted = ((double)num/1000.0).ToString("N1") + "k";
} else {
formatted = num.ToString("N0");
}
Điều đó sẽ in 36k cho đại diện của bạn, không 36.8k. Phiên bản StackOverflow giữ một số con số đáng kể. –
Nếu số lớn hơn một số ngưỡng, chia nó bằng 1000 và sau đó định dạng nó để tuy nhiên nhiều chữ số thập phân bạn cần .
int input = 12392; // for example
if (input >= 10000)
{
double thousands = input/1000.0;
Console.WriteLine(string.Format("{0}K", thousands));
}
Trả lại cho hiển thị là gì? – DOK
Bạn có thể thùng một CustomFormater như thế này:
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();
}
}
Và sử dụng nó như thế này:
String.Format(new KiloFormatter(), "{0:K}", 15600);
chỉnh sửa: đổi tên CurrencyFormatter để KiloFormatter
Con người, đó là rất nhiều mã chỉ để định dạng một số. – DOK
Phải đồng ý với DOK. Điều đó dường như khá dư thừa;) – CodeMonkey
@DOK: Đây là cách tiêu chuẩn để tạo các Form định dạng có thể tái sử dụng trong .NET Framework –
Đoạn code dưới đây được thử nghiệm lên to int.MaxValue Đây không phải là mã đẹp nhất nhưng hiệu quả nhất. Nhưng bạn có thể sử dụng nó như:
123.KiloFormat(); 4332.KiloFormat(); 2332124.KiloFormat(); int.MaxValue.KiloFormat(); (int1 - int2 * int3) .KiloFormat();
v.v ...
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");
}
}
tôi chỉ viết một số để cung cấp thông tin đầy đủ
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
};
}
}
Sử dụng:
var amountInfo = SIPrefix.GetInfo(10250, 2);
var amountInfo2 = SIPrefix.GetInfo(2500000, 0);
amountInfo.AmountWithPrefix // 10.25K
amountInfo2.AmountWithPrefix // 2M
tôi đã viết phương pháp này để rút gọn long
số:
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");
}
Một chút thay đổi v ersion của SLaks code
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");
}
này sẽ trả lại giá trị sau:
123 -> 123
1234 -> 1,234
12345 -> 12.35k
123456 -> 123.4k
1234567 -> 1.23M
12345678 -> 12.35M
123456789 -> 123.5M
Tôi biết đây là một chủ đề rất cũ, nhưng tôi nghĩ rằng một câu trả lời chung chung hơn có thể hữu ích:
ADD: bỏ qua rằng nó phải có được C#, vì vậy ở đây nó được dịch:
//--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.));
Console.WriteLine(FormatMetricPrefixF2US(0.000000));
Console.WriteLine(FormatMetricPrefixF2US(1.234567890E-26));
Console.WriteLine(FormatMetricPrefixF0US(0.5));
Console.WriteLine(FormatMetricPrefixF0US(2));
Console.WriteLine(FormatMetricPrefixF0US(20000));
Console.WriteLine(FormatMetricPrefixF0US(87654321));
}
Và điều này là dành cho SQL:
--Formats the number after scaling by factors of 1000, and appends a metric unit prefix (e.g. M for *1000000)
[email protected], @Cult are the standard FORMAT parameters (after metric scaling has been performed)
[email protected] (/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)
[email protected] 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 [email protected]
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 @[email protected]*POWER(1000.0,[email protected])
if 9<@idx set @[email protected]/POWER(1000.0,@idx-9)
end
Return FORMAT(@tmp,@mask,@Cult)+LTrim(Substring(@Prefixes,@idx,1))
end
GO
Và sau đó có lẽ một số hàm bao bọc có liên quan để giảm bớt việc sử dụng, ví dụ:
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
Và một loạt các thử nghiệm/ví dụ:
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.)+'g'
union Select 13, dbo.FormatMetricPrefixF2US(0.0)+'g'
union Select 14, dbo.FormatMetricPrefixF2US(0.00)+'g'
union Select 15, dbo.FormatMetricPrefixF2US(0.000)+'g'
union Select 16, dbo.FormatMetricPrefixF2US(0.0000)+'g'
union Select 17, dbo.FormatMetricPrefixF2US(0.00000)+'g'
union Select 18, dbo.FormatMetricPrefixF2US(0.000000)+'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());
}
> = là ý của bạn là gì? – CodeMonkey
@CodeMonkey: Có; cảm ơn. – SLaks
Trả lại cho số 12392 của Earwicker là bao nhiêu? – DOK