闲来无事,一时心血来潮,写了个数字转人民币大写的例子。其中主要的难点是“0”在不同位置,处理的方式有所不同。
这里考虑的是整数位为最多12位,小数位2位的通用数字。也就是最小值0.00,最大值为999999999999.99。
从左往右看,首先数字在整数部第4位,第8位与第12位为“0”时,不应转化为大写“零”。而在小数部的第2位也不应为零。
再者,若是某处数字为“0”,那么如果其前一位也是“0”的话,则同样不应转化为“零”,否则会出现“零零”这样的结果。
但是这有例外,比如100100.00这样的数字,第三位是“0”,第二位也是“0”,而按照习惯,是应该转成“壹拾万零壹佰元整”的。
所以要考虑将12位整数分为三个部分。若不足12位的话,前面加“0”补足。
当某一部分的某一数字不满足前一位不为“0”这一条件时,先要从当前部分查看是否之前有过非“0”的数字,若有则不需要加“零”。
如要当前部分还是不满足条件的话,则要继续向前查找,在前一部分寻找是否有非“0”的数字。找到的话则加“零”。
小数部分有个地方需要注意:当整数部分为0,小数部分第一位也是“0”时,不要将其转为“零”。
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
namespace Demo
{
internal class Program
{
private static Dictionary<char, string> _dic = new Dictionary<char, string>();
public static void Main(string[] args)
{
_dic['1'] = "壹";
_dic['2'] = "贰";
_dic['3'] = "叁";
_dic['4'] = "肆";
_dic['5'] = "伍";
_dic['6'] = "陆";
_dic['7'] = "柒";
_dic['8'] = "捌";
_dic['9'] = "玖";
_dic['0'] = "零";
while (true)
{
Test();
Thread.Sleep(1000);
}
}
private static void Test()
{
Random r = new Random();
int count = r.Next(0, 13);
int i = 0;
StringBuilder sb = new StringBuilder();
while (i++ < count)
{
sb.Append(r.Next(0, 10));
}
sb.Append(".");
i = 0;
while (i++ < 2)
{
sb.Append(r.Next(0, 10));
}
Console.WriteLine(ConverToRMB(Convert.ToDecimal(sb.ToString(), CultureInfo.InvariantCulture)));
}
private static string ConverToRMB(decimal num)
{
string data = Convert.ToString(num, CultureInfo.InvariantCulture);
bool isNum = ValidateData(data);
if (!isNum)
{
return "无效的数字";
}
string[] parts = data.Split('.');
string intPart = parts[0];
string decPart = parts[1];
string intResult = ParseIntPart(intPart);
bool isZero = String.IsNullOrEmpty(intResult);
string decResult = ParseDecPart(decPart, isZero);
string result = string.Empty;
if (String.IsNullOrEmpty(intResult))
{
if (String.IsNullOrEmpty(decResult))
{
result = "零元整";
}
else
{
result = decResult;
}
}
else
{
if (String.IsNullOrEmpty(decResult))
{
result = intResult + "元整";
}
else
{
result = intResult + "元" + decResult;
}
}
return result;
}
private static bool ValidateData(string data)
{
Regex r = new Regex(@"^\d{0,12}\.\d{2}$");
return r.IsMatch(data);
}
private static string ParseIntPart(string intPart)
{
char[] arr = intPart.ToCharArray();
char[] temp = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' };
arr.CopyTo(temp, 12 - arr.Length);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 3; i++)
{
StringBuilder s = new StringBuilder();
bool flag = false;
for (int j = 0; j < 4; j++)
{
char c = temp[j + i * 4];
if (c != '0')
{
s.Append(_dic[c]);
switch (j)
{
case 0: s.Append('仟'); break;
case 1: s.Append('佰'); break;
case 2: s.Append('拾'); break;
}
}
else
{
if (j != 3)
{
if (j != 0 && temp[j + i * 4 - 1] != '0')
{
for (int k = j; k < 4; k++)
{
if (temp[k + i * 4] != '0')
{
s.Append("零");
break;
}
}
}
else
{
if (i > 0)
{
for (int k = j; k >= 0; k--)
{
if (temp[k + i * 4] != '0')
{
flag = true;
break;
}
}
if (!flag)
{
bool flag2 = false;
for (int k = i-1; k >= 0; k--)
{
if (!flag2)
{
for (int m = 0; m < 4; m++)
{
if (temp[m + k * 4] != '0')
{
s.Append("零");
flag2 = true;
flag = true;
break;
}
}
}
}
}
}
}
}
}
}
if (s.Length > 0)
{
switch (i)
{
case 0: s.Append('亿'); break;
case 1: s.Append('万'); break;
}
sb.Append(s);
}
}
return sb.ToString();
}
private static string ParseDecPart(string decPart, bool isZero)
{
char[] arr = decPart.ToCharArray();
char c1 = arr[0];
char c2 = arr[1];
if (c1 == '0' && c2 == '0')
{
return string.Empty;
}
StringBuilder sb = new StringBuilder();
if (c1 != '0')
{
sb.Append(_dic[c1]);
sb.Append('角');
}
else
{
if (!isZero)
{
sb.Append("零");
}
}
if (c2 != '0')
{
sb.Append(_dic[c2]);
sb.Append('分');
}
return sb.ToString();
}
}
}
原文同步发布于我的 个人博客