曾经在N年前,也写过一个阿拉伯数字转大写金额的代码,但那时候对正则还不是很了解,Replace写的一长串一长串,现在用正则后,妥妥的几次Replace搞定,与其它转换代码相比,当然也要有点独特(或者说是画蛇添足)的地方,同时支持简体与繁体,好歹台湾同胞们用的都是繁体不是?当然大写金额国内也认可繁体的说……
代码不多,就一个枚举和一个静态类
枚举ChineseLanguage用于确认要转化成哪种中文
public enum ChineseLanguage
{
/// <summary>
/// 简体
/// </summary>
SimplifiedChinese = 0,
/// <summary>
/// 繁体
/// </summary>
TraditionalChinese = 1
}
ConvertIAmount为静态类,包含一个公开的扩展方法和两个私有的静态方法
using System.Text;
using System.Text.RegularExpressions;
public static class ConvertIAmount
{
/// <summary>
/// 中文的单位,不采用兆京等易产生误解的单位
/// </summary>
private static readonly string[] ChineseNumberUnits = { "万拾佰仟亿", "萬拾佰仟億" };
/// <summary>
/// 中文的数字
/// </summary>
private static readonly string[] ChineseNumbers = { "零壹贰叁肆伍陆柒捌玖", "零壹貳叁肆伍陸柒捌玖" };
/// <summary>
/// RMB计价单位
/// </summary>
private static readonly string[] RMBUnits = { "圆角分", "圓角分" };
/// <summary>
/// 将阿拉伯数字转换为中文人民币书写
/// </summary>
/// <param name="number">要转换的阿拉伯数字</param>
/// <param name="language">要转化为哪种中文,默认简体</param>
/// <returns></returns>
public static string ConvertChIAmount(this decimal number, ChineseLanguage language = ChineseLanguage.SimplifiedChinese)
{
if (number < 0)
{
throw new Exception("The number you want to change must be greater then zero.");
}
var integerPartNumber = decimal.ToUInt64(number);//整数部分
string integerPart = ConvertIntegerPart(integerPartNumber, language);
string decimalPart = ConvertDecimalPart((byte)((number - integerPartNumber) * 100), language);//低于二位的小数直接舍弃,不存在什么进制
if (string.IsNullOrEmpty(decimalPart))
{
//不包含小数时,增加 整 标志
return string.Format("{0} 整", integerPart);
}
else
{
//组织字符串并移除零圆(零圓)
return string.Format("{0} {1}", integerPart, decimalPart).Trim(ChineseNumbers[0][0], RMBUnits[0][0], RMBUnits[1][0]).Trim();
}
}
/// <summary>
/// 转化整数部分
/// </summary>
/// <param name="number">ulong.Max=1844 6744 0737 0955 1615</param>
/// <param name="language"></param>
/// <returns></returns>
private static string ConvertIntegerPart(ulong number, ChineseLanguage language)
{
string numbers = ChineseNumbers[(int)language];
string rmbUnits = RMBUnits[(int)language];
string numberUnits = ChineseNumberUnits[(int)language];
string returnStr;
StringBuilder tmp = new StringBuilder();
tmp.Append(rmbUnits[0]);//圆(圓)
for (var i = 0; ; i++)
{
if (i > 0)
{
if (i % 8 == 0)
{
tmp.Insert(0, numberUnits[4]);//亿(億)
}
else
{
tmp.Insert(0, numberUnits[i % 4]);//万(萬)拾佰仟
}
}
var tmpInt = number % 10;
tmp.Insert(0, numbers[(int)tmpInt]);
number /= 10;
if (number == 0) { break; }
}
string zero = numbers[0].ToString();
//将 零[拾佰仟] 替换成 零
returnStr = Regex.Replace(tmp.ToString(), string.Format("{0}[{1}{2}{3}]", numbers[0], numberUnits[1], numberUnits[2], numberUnits[3]), zero);
//将 零{2,} 替换成 零
returnStr = Regex.Replace(returnStr, string.Format("[{0}]{{2,}}", numbers[0]), zero);
//将 零(?=[万亿]) 替换成 空格
returnStr = Regex.Replace(returnStr, string.Format("{0}(?=[{1}{2}])", numbers[0], numberUnits[0], numberUnits[4]), string.Empty);
//将 (?<=[亿])万 替换成 空格
returnStr = Regex.Replace(returnStr, string.Format("(?<=[{0}]){1}", numberUnits[4], numberUnits[0]), string.Empty);
//将 (?<=[万拾佰仟亿])零(?=圆) 替换成 空格
returnStr = Regex.Replace(returnStr, string.Format("(?<=[{0}]){1}(?={2})", numberUnits, numbers[0], rmbUnits[0]), string.Empty);
return returnStr;
}
/// <summary>
/// 转化小数部分
/// </summary>
/// <param name="number"></param>
/// <param name="language"></param>
/// <returns></returns>
private static string ConvertDecimalPart(byte number, ChineseLanguage language)
{
string returnStr = string.Empty;
if (number > 0)
{
string numbers = ChineseNumbers[(int)language];
string rmbUnits = RMBUnits[(int)language];
returnStr = string.Format("{0}{1}{2}{3}", numbers[number / 10], rmbUnits[1], numbers[number % 10], rmbUnits[2]);
//将 零[角分] 替换成 空格
returnStr = Regex.Replace(returnStr, string.Format("{0}[{1}{2}]", numbers[0], rmbUnits[1], rmbUnits[2]), string.Empty);
}
return returnStr;
}
}
下面是测试代码
Console.WriteLine(ConvertIAmount.ConvertChIAmount(10000000100010.01m, ChineseLanguage.TraditionalChinese));//壹拾萬億零壹拾萬零壹拾圓 壹分
Console.WriteLine(ConvertIAmount.ConvertChIAmount(10000000100010.01m));壹拾万亿零壹拾万零壹拾圆 壹分
Console.WriteLine(ConvertIAmount.ConvertChIAmount(12060000100010.01m));//壹拾贰万零陆佰亿零壹拾万零壹拾圆 壹分
Console.WriteLine(ConvertIAmount.ConvertChIAmount(12060000100010.01m, ChineseLanguage.TraditionalChinese));//壹拾貳萬零陸佰億零壹拾萬零壹拾圓 壹分
写完看到一个帖子的29楼(方法里面double要改成decimal,不然在大数字的情况下会精度丢失)我就自卑了