【2021新】C#数字格式化字符串
引用来源: https://www.cnblogs.com/flyingbread/archive/2007/01/18/620287.html
https://www.cnblogs.com/1175429393wljblog/p/8399437.html
https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/standard-numeric-format-strings
定义
数字 格式化依赖于NumberFormatInfo 类,NumberFormatInfo对象的格式化值取决于当前线程的CultureInfo类。CultureInfo、NumberFormatInfo 类实现了 IFormatProvider。
每个区域的语言文化不一样,数字格式化的的结果也会不一样。CultureInfo就是操作当前系统区域性信息的类。tostring 方法通过CultureInfo类获取区域信息 格式化出不同的结果。如果我们要指定数据格式化出指定区域的的格式 如下操作:
CultureInfo cuinfo = new CultureInfo("af");//af是南非荷兰语
float dt =123456.789f;
Console.WriteLine(dt.ToString(cuinfo));// 123456,79
Console.WriteLine(CultureInfo.CurrentCulture.Name);//zh-CN 当前区域
Console.WriteLine(dt.ToString()); //123456.79
正文
如果你熟悉Microsoft Foundation Classes(MFC)的CString,Windows Template Library(WTL)的CString或者Standard Template Library(STL)的字符串类,那么你对String.Format方法肯定很熟悉。在C#中也经常使用这个方法来格式化字符串,比如下面这样:
decimal y = 3.57m;
string h = String.Format( $"item {x} sells at {y:C}");
Console.WriteLine(h);
在我的机器上,可以得到下面的输出:
也许你的机器上的输出和这个不太一样。 格式化货币(跟系统的环境有关,中文系统默认格式化人民币,英文系统格式化美元)英文操作系统结果:item 16 sells at $3.57
在我们日常使用中,更多的是使用Console.WriteLine方法来输出一个字符串。其实String.Format和Console.WriteLine有很多共同点。两个方法都有很多重载的格式并且采用无固定参数的对象数组作为最后一个参数。下面的两个语句会产生同样的输出。
string u = String.Format("Hello {0} {1} {2} {3} {4} {5} {6} {7} {8}", 123, 45.67, true, 'Q', 4, 5, 6, 7, '8');
Console.WriteLine(u);
输出如下:
Hello 123 45.67 True Q 4 5 6 7 8
2 字符串格式
String.Format和WriteLine都遵守同样的格式化规则。格式化的格式如下:"{ N [, M ][:Axx ]}", arg1, ... argN,在这个格式中:
1) N是从0开始的整数,表示要格式化的参数的个数
2) M是一个可选的整数,表示格式化后的参数所占的宽度,不足则补空格,如果M是负数,那么格式化后的值就是左对齐的,如果M是正数,那么格式化后的值是右对齐的。 如果 alignment 值小于设置了格式的字符串的长度,alignment 将被忽略,并使用设置了格式的字符串的长度作为字段宽度。 如果需要填充,则使用空白。 如果指定 alignment,则需要使用逗号。
3) A 另外一个可选的参数,表示格式代码 xx是精度精度说明符精度说明符的范围从 0 到 99,并且影响结果中的位数。 请注意,精度说明符指示结果字符串中所需的最少数字个数,不足的用0来填充。 它不舍入该数字。 若要执行舍入运算,请使用 Math.Ceiling、Math.Floor 或 Math.Round 方法
argN表示要格式化的表达式,和N是对应的。
如果argN是空值,那么就用一个空字符串来代替。如果没有formatString,那么就用参数N对应的ToString方法来格式化。下面的语句会产生同样的输出:
{
public static void Main(string[] args)
{
Console.WriteLine(123);
Console.WriteLine("{0}", 123);
Console.WriteLine("{0:D3}", 123);
}
}
输出是:
123
123
也可以通过String.Format得到同样的输出。
string t = string.Format("{0}", 123);
string u = string.Format("{0:D3}", 123);
Console.WriteLine(s);
Console.WriteLine(t);
Console.WriteLine(u);
因此有如下结论:
(,M)决定了格式化字符串的宽度和对齐方向
(:A)决定了如何格式化数据,比如用货币符号,科学计数法或者16进制。就像下面这样:
Console.WriteLine("{0,-5} {1,-5}", 123, 456); // 左对齐
输出是
123 456
也可以合并这些表达式,先放一个逗号,再放一个冒号。就像这样:
输出是:
我们可以用这种格式化特性来对齐我们的输出。
Console.WriteLine("----------------");
Console.WriteLine("{0,-10}{1,6}", "Bill", 123456);
Console.WriteLine("{0,-10}{1,6}", "Polly", 7890);
输出是:
----------------
Bill 123456
Polly 7890
3 格式化标识符
标准的数学格式字符串用于返回通常使用的字符串。它们通常象X0这样的格式。X是格式化标识符,0是精度说明符,精度说明符指示结果字符串中所需的最少数字个数,不足数的用0来填充。格式标识符号共有9种,它们代表了大多数常用的数字格式。就像下表所示:
D或d Decimal 十进制格式(十进制整数,不要和.Net的Decimal数据类型混淆了) :仅限整型类型
E或e Exponent 指数格式 :科学计数法 ,支持所有数值类型
F或f Fixed point 固定精度格式 : 默认保留两位小数,支持所有数值类型,
G或g General 常用格式 :结果:更紧凑的定点表示法或科学记数法 所有数值类型
Byte 或 SByte:3
Int16 或 UInt16:5
Int32 或 UInt32:10
Int64 或 UInt64:19
Single:7
Double:15
Decimal:29
N或n 用逗号分割千位的数字,比如1234将会被变成1,234 :结果:整数和十进制小数、组分隔符和十进制小数分隔符,负号可选支持:所有数值类型。
P或p Percentage 百分符号格式 默认保留两位小数
R或r Round-trip 圆整(只用于浮点数)保证一个数字被转化成字符串以后可以再被转回成同样的数字 :支持:Single、Double 和 BigInteger。
X或x Hex 16进制格式 结果:十六进制字符串,支持整型
如果我们使用下面的表达方式,让我们看看会发生什么
public class FormatSpecApp
{
public static void Main(string[] args)
{
int i = 123456;
Console.WriteLine($"{i:C}"); // ¥123,456.00
Console.WriteLine($"{i:D}"); // 123456
Console.WriteLine($"{i:E}"); // 1.234560E+005
Console.WriteLine($"{i:F}"); // 123456.00
Console.WriteLine($"{i:G}"); // 123456
Console.WriteLine($"{i:N}"); // 123,456.00
Console.WriteLine($"{i:P}"); // 12,345,600.00 %
Console.WriteLine($"{i:X}"); // 1E240
}
} 精度控制标识控制了有效数字的个数或者十进制数小数的位数。
Console.WriteLine($"{i:C5}"); // ¥123,456.00
Console.WriteLine($"{i:D5}"); // 123456
Console.WriteLine($"{i:E5}"); // 1.23456E+005
Console.WriteLine($"{i:F5}"); // 123456.00000
Console.WriteLine($"{i:G5}"); // 1.23456E5
Console.WriteLine($"{i:N5}"); // 123,456.00000
Console.WriteLine($"{i:P5}"); // 12,345,600.00000 %
Console.WriteLine($"{i:X5}"); // 1E240
R(圆整)格式仅仅对浮点数有效。这个值首先会用通用格式来格式化。对于双精度数有15位精度,对于单精度数有7位精度。如果这个值可以被正确地解析回原始的数字,就会用通用格式符来格式化。如果不能解析回去的话,那么就会用17位精度来格式化双精度数,
用9位精度来格式化单精度数。尽管我们可以在圆整标识符后面添加有效数字的位数,但是它会被忽略掉,不会进行四舍五入运算。
Console.WriteLine($"Floating-Point:\t{d:F16}", ); // 1.2345678901234567
Console.WriteLine($"Roundtrip:\t{d:R16}"); // 1.2345678901234567
如果标准格式化标识符还不能满足你。你可以使用图形化格式字符串来创建定制的字符串输出。图形化格式化使用占位符来表示最小位数,
最大位数,定位符号,负号的外观以及其它数字符号的外观。就像下表所示
符号 | 名称 | 含义 |
0 | 0占位符 | 用0填充不足的位数 |
# | 数字占位符 | 用#代替实际的位数 |
. | 十进制小数点 | |
, | 千位分隔符 | 用逗号进行千位分割,比如把1000分割成1,000 |
% | 百分符号 | 显示一个百分标识 |
E+0 E-0 e+0 e-0 |
指数符号 | 用指数符号格式化输出 |
\ | 专一字符 | 用于传统格式的格式化序列,比如"\n"(新行) |
'ABC' "ABC" |
常量字符串 | 显示单引号或者双引号里面的字符串 |
; | 区域分隔符 | 如果数字会被格式化成整数,负数,或者0,用;来进行分隔 |
,. | 缩放符号 | 数字除以1000 |
看下面的例子:
Console.WriteLine();
Console.WriteLine("{0:000000.00}", i); //123456.42
Console.WriteLine("{0:00.00000000e+0}", i); //12.34564200e+4
Console.WriteLine("{0:0,.}", i); //123
Console.WriteLine("{0:#0.000}", i); // 123456.420
Console.WriteLine("{0:#0.000;(#0.000)}", i); // 123456.420
Console.WriteLine("{0:#0.000;(#0.000);<zero>}", i); // 123456.420
Console.WriteLine("{0:#%}", i); // 12345642%
i = -123456.42;
Console.WriteLine();
Console.WriteLine("{0:000000.00}", i); //-123456.42
Console.WriteLine("{0:00.00000000e+0}", i); //-12.34564200e+4
Console.WriteLine("{0:0,.}", i); //-123
Console.WriteLine("{0:#0.000}", i); // -123456.420
Console.WriteLine("{0:#0.000;(#0.000)}", i); // (123456.420)
Console.WriteLine("{0:#0;(#0);<zero>}", i); // (123456)
Console.WriteLine("{0:#%}", i); // -12345642%
i = 0;
Console.WriteLine();
Console.WriteLine("{0:0,.}", i); //0
Console.WriteLine("{0:#0}", i); // 0
Console.WriteLine("{0:#0;(#0)}", i); // 0
Console.WriteLine("{0:#0;(#0);<zero>}", i); // <zero>
Console.WriteLine("{0:#%}", i); // %
4 数字字符串的解析
所有的基础类型都有ToString方法,它是从object类型中继承过来的。所有的数值类型都有Parse方法,它用字符串为参数,并且返回相等的数值。比如
{
public static void Main(string[] args)
{
int i = int.Parse("12345");
Console.WriteLine("i = {0}", i);
int j = Int32.Parse("12345");
Console.WriteLine("j = {0}", j);
double d = Double.Parse("1.2345E+6");
Console.WriteLine("d = {0:F}", d);
string s = i.ToString();
Console.WriteLine("s = {0}", s);
}
}
输出如下
j = 12345
d = 1234500.00
s = 12345
在缺省状况下,某些非数字字符是可以存在的。比如开头和结尾的空白。逗号和小数点,加号和减号,因此,下面的Parse语句是一样的
//double g = double.Parse(t); // 和下面的代码干同样的事情
double g = double.Parse(t,
NumberStyles.AllowLeadingSign |
NumberStyles.AllowDecimalPoint |
NumberStyles.AllowThousands |
NumberStyles.AllowLeadingWhite |
NumberStyles.AllowTrailingWhite);
Console.WriteLine("g = {0:F}", g);
输出都是这样
注意到,如果你要使用NumberStyles,就要添加对System.Globalization的引用,然后就可以使用不同NumberStyles的组合或者其中的任意一种。如果你想兼容货币符号,就需要使用重载的Parse方法,它们采用了NumberFormatInfo对象作为一个参数,然后你可以设置NumberFormatInfo的CurrencySymbol属性来调用Parse方法,比如:
NumberFormatInfo ni = new NumberFormatInfo();
ni.CurrencySymbol = "¥";
double h = Double.Parse(u, NumberStyles.Any, ni);
Console.WriteLine("h = {0:F}", h);
上面的代码有如下输出
除了NumberFormatInfo,还可以使用CultureInfo类。CultureInfo代表了某种特定的文化,包括文化的名字,书写的方式,日历的格式。对于某种特定文化的操作是非常普遍的情况,比如格式化日期和排序。文化的命名方式遵从RFC1766标准,使用<语言代码2>-<国家/地区码2>的方式,其中的<语言代码2>是两个小写的字母,它们来自ISO639-1;<国家/地区码2>是两个大写字母,它们来自ISO3166。比如,美国英语是“en-US"。英国英语是"en-GB"。特立尼达和多巴哥英语是"en-TT"。例如,我们可以创建一个美国英语的CultureInfo对象并且基于这种文化将数字转换成字符串。
CultureInfo us = new CultureInfo("en-US");
string v = k.ToString("c", us);
Console.WriteLine(v);
输出是:
要注意到,我们使用了重载的ToString方法,它把第一个格式化字符串当成第一个参数,将一个CultureInfo对象(执行了IFormatProvider对象)作为第二个参数。这儿有第二个例子,对于丹麦人来说:
string w = k.ToString("c", dk);
Console.WriteLine(w);
输出是:
5 字符串和日期
一个日期对象有个叫Ticks的属性。它存储了自从公元1年的1月1号上午12点开始的,以100纳秒为间隔的时间。比如,Ticks值等于31241376000000000L表示公元100年,星期五,1月1号,上午12点这一时间。Ticks总是以100纳秒为间隔递增。
DateTime的值以存储在DateTimeFormatInfo实例里面的标准或者自定义的方式来表示。为了修改一个日期显示的方式,DateTimeFormatInfo实例必须要是可写的,以便我们写入自定义的格式并且存入属性中
public class DatesApp
{
public static void Main(string[] args)
{
DateTime dt = DateTime.Now;
Console.WriteLine(dt);
Console.WriteLine("date = {0}, time = {1}\n",
dt.Date, dt.TimeOfDay);
}
}
代码会产生下面的输出
date = 23/06/2001 00:00:00, time = 17:55:10.3839296
下表列出了标准的格式字符串以及相关的DateTimeFormatInfo属性
D | ||
d | MM/dd/yyyy | ShortDatePattern(短日期模式) |
D | dddd,MMMM dd,yyyy | LongDatePattern(长日期模式) |
f | dddd,MMMM dd,yyyy HH:mm | Full date and time (long date and short time)(全日期和时间模式) |
F | dddd,MMMM dd,yyyy HH:mm:ss | FullDateTimePattern (long date and long time)(长日期和长时间) |
g | MM/dd/yyyy HH:mm | General (short date and short time)(通用模式,短日期和短时间) |
G | MM/dd/yyyy HH:mm:ss | General (short date and long time)(通用模式,短日期和长时间) |
M,M | MMMM dd | MonthDayPattern(月天模式) |
r,R | ddd,dd MMM yyyy,HH':'mm':'ss 'GMT' | RFC1123Pattern (RFC1123模式) |
S | yyyy-MM-dd HH:mm:ss | SortableDateTimePattern (conforms to ISO 8601) using local time(使用本地时间的可排序模式) |
T | HH:mm | ShortTimePattern (短时间模式) |
T | HH:mm:ss | LongTimePattern(长时间模式) |
U | yyyy-MM-dd HH:mm:ss | UniversalSortable-DateTimePattern (conforms to ISO 8601) using universal time(通用可排序模式) |
U | dddd,MMMM dd,yyyy,HH:mm:ss | UniversalSortable-DateTimePattern(通用可排序模式) |
y,Y | MMMM,yyyy | YearMonthPattern(年月模式) |
DateTimeFormatInfo.InvariantInfo属性得到了默认的只读的DateTimeFormatInfo实例,它与文化无关。你可以创建自定义的模式。要注意到的是InvariantInfo不一定和本地的格式一样。Invariant等于美国格式。另外,如果你向DateTime.Format方法传递的第二个参数是null,DateTimeFormatInfo将会是默认的CurrentInfo。比如
Console.WriteLine(dt.ToString("d", null));
Console.WriteLine();
输出是
23/06/2001
对比选择InvariantInfo和CurrentInfo的。
Console.Write("[I]nvariant or [C]urrent Info?: ");
if (Console.Read() == 'I')
dtfi = DateTimeFormatInfo.InvariantInfo;
else
dtfi = DateTimeFormatInfo.CurrentInfo;
DateTimeFormatInfo dtfi = DateTimeFormatInfo.InvariantInfo;
Console.WriteLine(dt.ToString("D", dtfi));
Console.WriteLine(dt.ToString("f", dtfi));
Console.WriteLine(dt.ToString("F", dtfi));
Console.WriteLine(dt.ToString("g", dtfi));
Console.WriteLine(dt.ToString("G", dtfi));
Console.WriteLine(dt.ToString("m", dtfi));
Console.WriteLine(dt.ToString("r", dtfi));
Console.WriteLine(dt.ToString("s", dtfi));
Console.WriteLine(dt.ToString("t", dtfi));
Console.WriteLine(dt.ToString("T", dtfi));
Console.WriteLine(dt.ToString("u", dtfi));
Console.WriteLine(dt.ToString("U", dtfi));
Console.WriteLine(dt.ToString("d", dtfi));
Console.WriteLine(dt.ToString("y", dtfi));
Console.WriteLine(dt.ToString("dd-MMM-yy", dtfi));
输出是
01/03/2002
03/01/2002
Thursday, 03 January 2002
Thursday, 03 January 2002 12:55
Thursday, 03 January 2002 12:55:03
01/03/2002 12:55
01/03/2002 12:55:03
January 03
Thu, 03 Jan 2002 12:55:03 GMT
2002-01-03T12:55:03
12:55
12:55:03
2002-01-03 12:55:03Z
Thursday, 03 January 2002 12:55:03
01/03/2002
2002 January
03-Jan-02
[I]nvariant or [C]urrent Info?: C
03/01/2002
03/01/2002
03 January 2002
03 January 2002 12:55
03 January 2002 12:55:47
03/01/2002 12:55
03/01/2002 12:55:47
03 January
Thu, 03 Jan 2002 12:55:47 GMT
2002-01-03T12:55:47
12:55
12:55:47
2002-01-03 12:55:47Z
03 January 2002 12:55:47
03/01/2002
January 2002
03-Jan-02
/******************************************************************************************
*【Author】:flyingbread
*【Date】:2007年1月18日
*【Notice】:
*1、本文为原创技术文章,首发博客园个人站点(http://flyingbread.cnblogs.com/),转载和引用请注明作者及出处。
*2、本文必须全文转载和引用,任何组织和个人未授权不能修改任何内容,并且未授权不可用于商业。
*3、本声明为文章一部分,转载和引用必须包括在原文中。
******************************************************************************************/
【2021新】C#数字格式化字符串的更多相关文章
- 第3.11节 Python强大的字符串格式化新功能:format字符串格式化的格式控制
第3.11节 format字符串格式化的格式控制 一. 引言 上节介绍了四种format进行字符串格式化的 ...
- JAVA中String.format的用法 格式化字符串,格式化数字,日期时间格式化,
1.对整数进行格式化:%[index$][标识][最小宽度]转换方式 我们可以看到,格式化字符串由4部分组成,其中%[index$]的含义我们上面已经讲过,[最小宽度]的含义也很好理解, ...
- Freemarker 内置函数 数字、字符串、日期格式化用法介绍
在用FreeMarker过程中,感觉FreeMarker的字符串,日期,集合等处理能力还是很强大的,上网搜了一些资料,整理如下,以便能帮助大家更熟练的应用Freemarker完成项目开发. 一.Seq ...
- C# String.Format 格式化字符串 数字/时间
首先献给只想知道结果的人 格式化 DateTime 对象 标准 数字 格式化 Int Decimal Float Double 关于这一块一直不是很清楚,MSDN 上也不够清晰. 就花了点时间敲了一下 ...
- R语言格式化数字和字符串format函数
数字和字符串可以使用 format()函数的格式化为特定样式. 语法 format()函数的基本语法是: format(x, digits, nsmall,scientific,width,justi ...
- C#定义类型转化 及 格式化字符串
operator 关键字 operator 关键字用来重载内置运算符,或提供类/结构声明中的用户定义转换.它可以定义不同类型之间采用何种转化方式和转化的结果. operator用于定义类型转化时可采用 ...
- C# 格式化字符串,日期,字符串操作汇总
时间格式化 有时候我们要对时间进行转换,达到不同的显示效果 默认格式为:2005-6-6 14:33:34 如果要换成成200506,06-2005,2005-6-6或更多的该怎么办呢 我们要用到:D ...
- C# 格式化字符串(转载)
1 前言 如果你熟悉Microsoft Foundation Classes(MFC)的CString,Windows Template Library(WTL)的CString或者Standard ...
- 上篇:python的基本数据类型以及对应的常用方法(数字、字符串、布尔值)
为了日后便于查询,本文所涉及到的必记的基本字符串方法如下: "分隔符".join(字符串) #将字符串的每一个元素按照指定分隔符进行拼接.split("字符串&qu ...
随机推荐
- JavaCV的摄像头实战之一:基础
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于<JavaCV的摄像头实战>系列 &l ...
- JUC之阻塞队列(BlockingQueue)基础
阻塞队列 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列.这两个附加的操作支持阻塞的插入和移除方法. 阻塞队列常用于生产者和消费者的场景: 当队列为空的,从队列中获取元素的操作将会 ...
- elasticsearch启动错误解决办法
1.max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] 解决: [r ...
- PyTorch 介绍 | BUILD THE NEURAL NETWORK
神经网络由对数据进行操作的layers/modules组成.torch.nn 命名空间提供了所有你需要的构建块,用于构建你自己的神经网络.PyTorch的每一个module都继承自nn.Module. ...
- C++学习Day 1
c++的函数需要声明才能再写他的定义,声明可以写多次,如果执行在main之前可以不写,全写不会犯错,现在看好像c++的函数定义里没有out,也没有变量的public和private(后面有再改) 声明 ...
- 湖人季后赛淘汰出局 - For James 2021.6.4
今天有NBA季后赛湖人主场对太阳的G6比赛,之前湖人2-3落后,这场比赛输了就被淘汰了.上午特意看了比赛的直播,期望着湖人能赢下这场,这样还有打G7的机会,也就还有进入下一轮的机会.最后湖人还是输了这 ...
- 各种形式存放token
1.可以将token存储在 localstorage里面,在一个统一的地方复写请求头,让每次请求都在header中带上这个token, 当token失效的时候,后端肯定会返回401,这个时候在你可以在 ...
- OC和JS代码的互调
01 OC调用JS的代码 NSString *str = [self.webView stringByEvaluatingJavaScriptFromString:@"sum()" ...
- linux centos6.3 升级svn1.6到svn1.8
linux centos6.3 升级svn1.6 1. 删除svn1.6 #yum remover subverson12.设置svn1.8安装源 vim /etc/yum.repos.d/wandi ...
- 入门- k8s发布应用服务 (五)
目标 了解 Kubernetes 的 Service(服务) 了解 Labels(标签)和 LabelSelector(标签选择器)与 Service(服务)的关系 在 kubernetes 集群中, ...