您的位置:首页 > 编程语言 > C#

C#人民币金额大写

2016-08-04 21:00 1486 查看
摘自《31天学会CRM项目开发<C#编程入门级项目实战>》

这是一项经典编程题,笔者也曾将此题作为面试题。

1.    业务要求

人民币大写金额用到的汉字主要包括零、壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿等。人民币大写金额有如下注意事项:

    中文大写金额数字到“元”为止的,在“元”之后、应写“整”(或“正”)字;在“角”之后,可以不写“整”(或“正”)字;大写金额数字有“分”的,“分”后面不写“整”(或“正”)字。

    阿拉伯数字中间有“0”时,中文大写要写“零”字,如¥1308.6应写成壹仟叁佰零捌元陆角;

    阿拉伯数字中间连续有几个“0”时、中文大写金额中间可以只写一个“零”字,如¥9006.24应写成玖仟零陆元贰角肆分。

    阿拉伯金额数字中间连续有几个“0”时,中文大写金额仅写一个零,如¥10001,应写成一万零一。

    阿拉伯金额数字角位是“0”而分位不是“0”时,中文大写金额“元”后面应写“零”字。

2.    实现方法

(1)    方法一

如片段9-20所示,主要步骤如下:

1)    取得整数和小数部分

2)    对整数部分进行反转,依次从个位数起添加数量单位

3)    将阿拉伯数字替换成大写数字

4)    替换不符合汉语规律的词汇,例如仟佰、零佰、零拾等

代码片段9-20

private string ConvertToChinese(double dou)
{
// 大写数字数组
string[] num = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
// 数量单位数组,个位数为空
string[] unit = { "", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "兆" };
string d = dou.ToString();
string zs = string.Empty;// 整数
string xs = string.Empty;// 小数
int i = d.IndexOf(".");
string str = string.Empty;
if (i > -1)
{
// 仅考虑两位小数
zs = d.Substring(0, i);
xs = d.Substring(i + 1, d.Length - i - 1);
str = "元";
if (xs.Length == 1)
str = str + xs + "角";
else if (xs.Length == 2)
str = str + xs.Substring(0, 1) + "角" + xs.Substring(1, 1) + "分";
}
else
{
zs = d;
str = "元整";
}
// 处理整数部分
if (!string.IsNullOrEmpty(zs))
{
i = 0;
// 从整数部分个位数起逐一添加单位
foreach (char s in zs.Reverse())
{
str = s.ToString() + unit[i] + str;
i++;
}
}
// 将阿拉伯数字替换成中文大写数字
for (int m = 0; m < 10; m++)
{
str = str.Replace(m.ToString(), num[m]);
}
// 替换零佰、零仟、零拾之类的字符
str = Regex.Replace(str, "[零]+仟", "零");
str = Regex.Replace(str, "[零]+佰", "零");
str = Regex.Replace(str, "[零]+拾", "零");
str = Regex.Replace(str, "[零]+亿", "亿");
str = Regex.Replace(str, "[零]+万", "万");
str = Regex.Replace(str, "[零]+", "零");
str = Regex.Replace(str, "亿[万|仟|佰|拾]+", "亿");
str = Regex.Replace(str, "万[仟|佰|拾]+", "万");
str = Regex.Replace(str, "仟[佰|拾]+", "仟");
str = Regex.Replace(str, "佰拾", "佰");
str = Regex.Replace(str, "[零]+元整", "元整");
return str;
}


(2)    方法二

使用正则表达式,如片段9-21所示,来源于网络,相比常规方法,显得非常简洁,足以展示正则表达式的强大,也体现了程序设计者深厚技术功底。由于无法查证这段代码的原作者,此处无法标注原作者姓名和出处。

代码片段9-21

string s =
dou.ToString("#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H#E#D#C#G#E#D#C#F#E#D#C#.0B0A");
string d = Regex.Replace(s,
@"((?<=-|^)[^\-1-9]*)|((?'z'0)[0A-E]*((?=[1-9])|(?'-z'(?=[F-L\.]|$))))
|((?'b'[F-L])(?'z'0)[0A-L]*((?=[1-9])|(?'-z'(?=[\.]|$))))", "${b}${z}");
string RMB= "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟万亿兆京垓秭穰";
string r = Regex.Replace(d, ".", m => RMB[m.Value[0] - '-'].ToString());
if (r.EndsWith("元"))
r = r + "整";


行6,“m.Value[0] - '-'”是两个char字符相减,char字符相减会升级为int型,相当于“(int)m.Value[0] – (int)'-'”,即使用char字符所对应的ASCII码值相减。

行6,符号“=>” 称作Lambda 表达式,是一种可用于创建委托或表达式目录树类型的匿名函数。通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数。若要创建 Lambda 表达式,需要在 Lambda 运算符 => 左侧指定输入参数(如果有),然后在另一侧输入表达式或语句块。 例如,lambda 表达式 x => x * x 指定名为 x 的参数并返回 x 的平方值。

行6可改写成如片段9-22形式。

代码片段9-22
string value = Regex.Replace(d, ".",
delegate(Match m){ return RMB[m.Value[0] - '-'].ToString(); });
片段9-22还可写成片段9-23、9-24形式,这样更容易理解。

代码片段9-23
string r = Regex.Replace(d, ".", new MatchEvaluator(GetChinese));

代码片段9-24

private string GetChinese(Match m)
{
string RMB = "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟万亿兆京垓秭穰";
return RMB[m.Value[0] - '-'].ToString();
}
方法一属于常规思路,一般人都会这么考虑,方法二,打破常规,非正则不“娶”,充分体现了程序设计者对代码简洁苛刻的追求。方法一虽然代码比较长,但也有优点,它还适用于Java、JavaScript、PHP等其他编程语言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C#