现在的位置: 首页 > 综合 > 正文

让.NET(C#)更好地为中国人输出数字

2012年12月28日 ⁄ 综合 ⁄ 共 2726字 ⁄ 字号 评论关闭

来看一个比较长的数字在.NET下的输出:

//+ using System.Globalization;

//+ using System.Threading;

 

//把当前线程的CultureInfo改成中文-中国"

Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("zh-cn");

 

decimal m = 987654321;

 

Console.WriteLine(m);

Console.WriteLine(m.ToString("N"));

Console.WriteLine(m.ToString("C"));

 

输出:

987654321

987,654,321.00

¥987,654,321.00

 

显然第一种输出最不可取,没有分隔符,太难分辨数位了。

但是后面的输出虽然用了格式化输出符,并且当前线程的CultureInfo也是“中文-中国”,但是.NET Framework还是会按照英文数字的模式进行输出(除了货币符号是中文的¥)。这是为了“国际化”?

 

管它什么化,反正这个数字中国人读起来肯定不爽。因为我们从小学习数字读法都是以4个位做分隔:个十百千,万十万百万千万,亿。九个数正好是九亿开始。而这个数是以3位做分隔,我们还是得数位数。这个数其实还是为熟悉英语的人服务的,他们可以很好得读出来:nine hundred and eighty-seven million, six hundred and fifty-four thousand, three hundred and twenty-one。人家直接把两个逗号读成million和thousand就可以了。

 

改进方法就是自定义CultureInfo(事实上是在自定义一个IFormatProvider,后面会讲),设置的对象就是CultureInfo的NumberFormatInfo。

 

NumberFormatInfo中的GroupSizes和GroupSeparator对应数字的数位分隔长度和分隔符。另外NumberFormatInfo中的属性的设置根据Currency,Number和Percentage分别对应输出时的C,G和P格式化标识符。(当直接调用ToString没有任何参数相当于G参数)。

 

下面程序实例中就以CurrencyGroupSizes,CurrencyGroupSeparator和NumberGroupSizes,NumberGroupSeparator做示例,读者可以举一反三。当然NumberFormatInfo不限于这些属性,推荐读者阅读下MSDN做延伸:http://msdn.microsoft.com/zh-cn/library/system.globalization.numberformatinfo

 

我们的目的很简单,把3位分隔改成4位分隔,并且把分隔符逗号替换成空格。(因为有些人会把逗号错看成小数点)

 

代码:

//+ using System.Globalization;

//+ using System.Threading;

 

//修改CultureInfo的NumberFormatInfo

var culture = (CultureInfo)CultureInfo.GetCultureInfo("zh-cn").Clone();

culture.NumberFormat.NumberGroupSizes =

    culture.NumberFormat.CurrencyGroupSizes = new int[] { 4 };

culture.NumberFormat.NumberGroupSeparator =

    culture.NumberFormat.CurrencyGroupSeparator = " ";

 

//设置成当前线程的CultureInfo

Thread.CurrentThread.CurrentCulture = culture;

 

decimal m = 987654321;

 

Console.WriteLine(m.ToString("N"));

Console.WriteLine(m.ToString("C"));

 

输出:

9 8765 4321.00

¥9 8765 4321.00

 

很好!这下什么数字一目了然了。九亿 八千七百六十五万 四千三百二十一!

 

还有一个问题,如果你不方便修改线程的CultureInfo的话(或许你的程序依赖当前操作系统的CultureInfo不能随意修改,因为一旦修改了线程的CultureInfo,所有输出都会以这种方式的)。其实细细学.NET的话,你会发现CultureInfo和NumberFormatInfo都继承IFormatProvider接口,同时.NET中的字符输出方法(ToString和String.Format方法)都提供自定义的IFormatProvider的。

 

代码:

//+ using System.Globalization;

 

//修改CultureInfo的NumberFormatInfo

var culture = (CultureInfo)CultureInfo.GetCultureInfo("zh-cn").Clone();

culture.NumberFormat.NumberGroupSizes =

    culture.NumberFormat.CurrencyGroupSizes = new int[] { 4 };

culture.NumberFormat.NumberGroupSeparator =

    culture.NumberFormat.CurrencyGroupSeparator = " ";

 

decimal m = 987654321;

 

//使用当前线程的CultureInfo

Console.WriteLine(m.ToString("N"));

//使用CultureInfo作为IFormatProvider

Console.WriteLine(m.ToString("N", culture));

//使用NumberFormatInfo作为IFormatProvider

Console.WriteLine(m.ToString("N", culture.NumberFormat));

//String.Format方法也有IFormatProvider

Console.WriteLine(String.Format(culture, "{0:N}", m));

 

输出:

987,654,321.00

9 8765 4321.00

9 8765 4321.00

9 8765 4321.00

 

 

Open-mouthed smile

【上篇】
【下篇】

抱歉!评论已关闭.