人民币大小写转换~~

首先,数字应该分段,分成万以下的、万、亿、兆这几个段,并且每个段的长度固定是4个数字。比如说 123456 分为两个段,前面一个未满的段:12 ,后面是满的段:3456 。

其次,每个满段其实都是个十百千四个单位。比如:12345678 ,转成数字大写是:壹仟贰佰叁拾肆 万 伍仟陆佰柒拾捌,发现什么规律了吗?

最后,就是处理一些必须有 0 的问题了,比如说:303 ,不能说:叁佰叁,应该是:叁佰零叁,这个“零”有很多讲究的。

 

针对这些规律,我有针对性的整理出来两个方法:SingleConvert 、MultiConvert 。其中 SingleConvert 处理段内的逻辑,MultiConvert 处理段间的逻辑,在段内的数字 0 问题穿插到 SingleConvert 方法中,段间的数字 0 问题穿插到 MultiConvert 方法中。另外,小数部分的处理,只有两位数字,可以写死,这个最简单了。

 

说一下数字 0 的逻辑。

 

数字【3003】转换出来应该是【叁仟零叁】,数字【303】转换出来应该是【叁佰零叁】,可以看到段内连续出现一个或多个数字 0 的情况下,只会出现一个汉字【零】。

数字【3000000000300】转换出来应该是【叁兆零叁佰】,数字【300000300】转换出来应该是【叁亿零叁佰】,可以看到段间连续出现一个或多个数字 0 的情况下,只会出现一个汉字【零】。

所以,段内逻辑和段间逻辑,在连续出现多个【零】的时候,只保留一个【零】

 

数字【300】转换出来应该是【叁佰】,数字【3000】转换出来应该是【叁仟】,可以看到在段内最后不管连续出现多少【零】,都抹掉不提。

所以,段内逻辑中,末尾的一个或多个【零】,均不保留

 

还有两个不值得提的规律:每个数字对应一个单位,必定是【个十百千】;每段对应一个单位,从低到高的对应是【空、万、亿、兆、……】

原谅我不知大更高的单位是什么了,这辈子没见过那么多钱,神那~~

 

然后,然后就没规律了,下面上代码:

 
 
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; namespace Lenic.Core { /// <summary> /// 数字转大写汉字字符类 /// </summary> [DebuggerStepThrough] public class NumericConvert { #region Private Fields /// <summary> /// 段的分隔字符,从低到高依次增加:空、万、亿、万亿,最高不超过万亿的数字都可以 /// </summary> public static readonly string[] DefaultRangeNumeric = new string[] { string.Empty, " ", " 亿 ", " " }; /// <summary> /// 位的分隔字符,从低到高依次是:仟、佰、拾、空 /// </summary> public static readonly char[] DefaultUnitNumeric = new char[] { ' ', ' ', ' ', char.MinValue }; /// <summary> /// 数字替换的字符,从低到高依次是:零、壹、贰、叁、肆、伍、陆、柒、捌、玖 /// </summary> public static readonly char[] DefaultCharNumeric = new char[] { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; private char[] charNumeric = DefaultCharNumeric; private string[] rangeNumeric = DefaultRangeNumeric; private char zeroNumeric = DefaultCharNumeric[ 0]; private char[] unitNumeric = DefaultUnitNumeric; #endregion #region Business Methods /// <summary> /// 重置数字替换的字符,必须从小到大是 10 个汉字字符。 /// </summary> /// <param name="data"> 目标字符数组 </param> /// <returns> 成功替换则返回 <c> true </c> </returns> public bool ResetCharNumeric( char[] data) { if (data == null || data.Length != 10) return false; charNumeric = data; zeroNumeric = data[ 0]; return true; } /// <summary> /// 重置位的分隔字符,必须从小到大是 4 个汉字字符。 /// </summary> /// <param name="data"> 目标字符数组 </param> /// <returns> 成功替换则返回 <c> true </c> </returns> public bool ResetUnitNumeric( char[] data) { if (data == null || data.Length != 4) return false; unitNumeric = data; return true; } /// <summary> /// 重置段的分隔字符。 /// </summary> /// <param name="data"> 目标字符数组 </param> public void ResetRangeNumeric( string[] data) { rangeNumeric = data ?? DefaultRangeNumeric; } /// <summary> /// 执行数字转大写汉字字符的操作。 /// </summary> /// <param name="obj"> 待转换的数字 </param> /// <returns> 转换完成的大写汉字字符串。 </returns> public string Convert( decimal obj) { if (obj > 9999999999999999.99M) throw new ApplicationException( " The numeric too big! "); var data = obj.ToString( " #.## "); var list = data.Split( ' . '); var result = MultiConvert(list[ 0]); if (list.Length > 1) result += DecimalConvert(list[ 1]); return result; } #endregion #region Private Methods private string MultiConvert( string data) { var list = Split(data).ToArray(); var results = new List< string>(); foreach ( var item in list) results.Add(SingleConvert(item)); var sbResult = new StringBuilder(); var len = results.Count; var index = len - 1; for ( int i = 0; i < len; i++) { var item = results[i]; if ((i + 2 < len) && item == zeroNumeric.ToString() && results[i + 1].StartsWith(zeroNumeric.ToString())) continue; if (!(i == (len - 1) && item == zeroNumeric.ToString())) sbResult.Append(item); var unit = rangeNumeric[index - i]; if (unit != string.Empty && item != zeroNumeric.ToString()) sbResult.Append(unit); } if (sbResult[sbResult.Length - 1] == zeroNumeric) sbResult.Remove(sbResult.Length - 1, 1); sbResult.Append( " "); return sbResult.ToString(); } private string SingleConvert( string data) { var len = data.Length; var result = new List< char>(); var previousChar = char.MinValue; var unitIndex = len == 4 ? 0 : ( 4 - len); for ( int i = 0; i < len; i++) { var item = CharToInt(data[i]); var currentChineseChar = charNumeric[item]; if (currentChineseChar == previousChar && previousChar == zeroNumeric && currentChineseChar == zeroNumeric) continue; else { result.Add(previousChar = currentChineseChar); var currentUnit = unitNumeric[unitIndex + i]; if (currentChineseChar != zeroNumeric && currentUnit != char.MinValue) result.Add(currentUnit); } } if (result.Count != 1 && result.Last() == zeroNumeric) result.RemoveAt(result.Count - 1); return new string(result.ToArray()); } private string DecimalConvert( string data) { StringBuilder sbResult = new StringBuilder(); if (data[ 0] != ' 0 ') { sbResult.Append(charNumeric[CharToInt(data[ 0])]); sbResult.Append( " "); } if (data[ 1] != ' 0 ') { sbResult.Append(charNumeric[CharToInt(data[ 1])]); sbResult.Append( " "); } return sbResult.ToString(); } private IEnumerable< string> Split( string data) { var len = data.Length / 4; var mod = data.Length % 4; if (mod != 0) len += 1; var startIndex = 0; var blockLength = mod != 0 ? mod : 4; for ( int i = 0; i < len; i++) { yield return data.Substring(startIndex, blockLength); startIndex += blockLength; blockLength = 4; } } private int CharToInt( char obj) { return (( int)obj) - 48; } #endregion } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值