数字转人民币大写算法一则
闲来无事,一时心血来潮,写了个数字转人民币大写的例子。其中主要的难点是“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(); } } }
原文同步发布于我的个人博客