最近有个需求,需要显示汉字数字,比如一二三四五…这样子,问题看起来挺简单,但我没有找到有自带这样的转换的方法,数字转汉字数字,挺有意思的,就简单研究了一下;
百度了一下,有个基本的思路就是预定义有个数字,直接取:
var baseStr = new List<string>() { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十",};
直接按下标就能实现1~10的转换了;
但是超过10怎么办呢?不可能把所有数字预定义啊。那就组合拼装一下:
var baseStr = new List<string>() { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九", };
var signs = new List<string>() { "十", "百", "千", "万",}
一下子就把范围扩大大99999了,通过各个位数的值,进行转换,这样你就可以会得到 “一十”,“一十一”,“一百零” ,“三千零零五”,这样不符合表达的结果;
算了,文章不会写。总之,经过一系列的演化,直接上源码吧;
准备好预定义的汉字数字(兆后面都是百度来的):
var signs = new List<string>() { "十", "百", "千", "万", "亿", "兆", "京", "垓", "秭", "穰", "沟", "涧", "正", "载", "极", "恒河沙", "阿僧祇", "那由他", "不可思议", "无量大数" };var baseStr = new List<string>() { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九", };
做个初始判断,支持正负号:
var charFirst = numStr.First();int startNumIndex = 0;string firstSign = string.Empty;if (!char.IsNumber(charFirst)){if (!charFirst.Equals('-')){if (!charFirst.Equals('+')){outString = $"输入参数第一位“ {charFirst} ”既不是数字也不是正负符号。";return false;}firstSign = "正";}else{firstSign = "负";}startNumIndex = 1;}var realStr = numStr.Substring(startNumIndex, numStr.Length - startNumIndex);realStr.Trim();realStr.ToList().RemoveAll(p => !char.IsNumber(p));var strTemp = realStr.ToString();if (string.IsNullOrEmpty(strTemp)){outString = $"输入参数“ {numStr} ”没有数字!";return false;}
从各位开始判断,拼接字符串:
var werishu = strTemp.Length;var strReverse = strTemp.Reverse().ToList();var strResult = string.Empty;bool isShowZero = ShowZero();for (int index = 0; index < werishu; index++){var ch = strReverse[index];var tempNumber = int.Parse(ch.ToString());strResult = $"{Trans(tempNumber, index - 1, isShowZero)}{strResult}";if (tempNumber == 0){isShowZero = false;}}outString = $"{firstSign}{strResult}";return true;
是否显示“零的判断”,处理“一百”,“一千”,“一万” 这样的情况
bool ShowZero(){var sub1 = strTemp.IndexOf("0");bool need0 = false;if (sub1 != -1){var less = strTemp.Length - sub1 - 1;if (werishu == 1 ||(less > 0 && strTemp.Substring(sub1 + 1).Count(p => p.Equals('0')) != less)){// 不是连续的0,要保留显示“零”need0 = true;}}return need0;}
转换逻辑,按位取对应数字和单位
string Trans(int value, int signIndex, bool showZero){if (value == 1 && signIndex == 0){return signs[signIndex];}var strSign = signs[0];strSign = CalSign(signIndex); var tempResult = $"{GeStr(value, showZero)}{strSign }";return tempResult;}
获取对应数字的逻辑:
string GeStr(int baseStrIdex, bool showZero){if (showZero){return baseStr[baseStrIdex];}return baseStrIdex == 0 ? string.Empty : baseStr[baseStrIdex];}
重点来了,单位计算,比如十万~千万,是单位与单位的拼接:
string CalSign(int signIndex){var strSign = string.Empty;var realSignIndex = signIndex;if (realSignIndex < 4){return GetSignStr(realSignIndex);}int signSecond = 4; // 到亿if (realSignIndex < 7){// 到亿return $"{GetSignStr(signIndex - signSecond)}";}if (realSignIndex == 7){return GetSignStr(signSecond);}realSignIndex -= 7;var signLen = 4;var n = realSignIndex / signLen;if (realSignIndex == n * signLen){return GetSignStr(n + signSecond);}return strSign = $"{GetSignStr(realSignIndex - (n * signLen) - 1)}";string GetSignStr(int indexTemp){return indexTemp == -1 ? string.Empty : signs[indexTemp];}}
至此,完成!
全部带入如下,复制粘贴即可
public bool GetChineseNumber(string numStr, out string outString){outString = string.Empty;if (!CheckValid(numStr, ref outString, out var strTemp, out var firstSign)){return false;}var signs = new List<string>() { "十", "百", "千", "万", "亿", "兆", "京", "垓", "秭", "穰", "沟", "涧", "正", "载", "极", "恒河沙", "阿僧祇", "那由他", "不可思议", "无量大数" };var baseStr = new List<string>() { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九", };bool isShowZero = IsShowZero(strTemp);var len = strTemp.Length;var strReverse = strTemp.Reverse().ToList();var strResult = string.Empty;for (int index = 0; index < len; index++){var ch = strReverse[index];var tempNumber = int.Parse(ch.ToString());var signIndex = index - 1;string tempResult;if (tempNumber == 1 && signIndex == 0 && len == 2){tempResult = signs[signIndex];}else{ var strSign = CalSign(signIndex, signs);var showZero = isShowZero && index > 0;tempResult = $"{GeStr(tempNumber, showZero, baseStr)}{strSign}";}strResult = $"{tempResult}{strResult}";if (tempNumber == 0){isShowZero = false;}}outString = $"{firstSign}{strResult}";return true;}private bool CheckValid(string numStr, ref string outString, out string realNumberString, out string firstSign){realNumberString = string.Empty;var charFirst = numStr.First();var startNumIndex = 0;firstSign = string.Empty;if (!char.IsNumber(charFirst)){if (!charFirst.Equals('-')){if (!charFirst.Equals('+')){outString = $"输入参数第一位“ {charFirst} ”既不是数字也不是正负符号。";return false;}firstSign = "正";}else{firstSign = "负";}startNumIndex = 1;}var realStr = numStr.Substring(startNumIndex, numStr.Length - startNumIndex);realStr.Trim();realStr.ToList().RemoveAll(p => !char.IsNumber(p));realNumberString = realStr.ToString();if (string.IsNullOrEmpty(realNumberString)){outString = $"输入参数“ {numStr} ”没有数字!";return false;}return true;}private string CalSign(int signIndex, List<string> signs){var realSignIndex = signIndex;if (realSignIndex < 4){return GetSignStr(realSignIndex);}int signSecond = 4; // 到亿if (realSignIndex < 7){// 到亿return $"{GetSignStr(signIndex - signSecond)}";}if (realSignIndex == 7){return GetSignStr(signSecond);}realSignIndex -= 7;var signLen = 4;var n = realSignIndex / signLen;if (realSignIndex == n * signLen){return GetSignStr(n + signSecond);}string strSign;return strSign = $"{GetSignStr(realSignIndex - (n * signLen) - 1)}";string GetSignStr(int indexTemp){return indexTemp == -1 ? string.Empty : signs[indexTemp];}}private string GeStr(int baseStrIdex, bool showZero, List<string> baseStr){if (showZero){return baseStr[baseStrIdex];}return baseStrIdex == 0 ? string.Empty : baseStr[baseStrIdex];}private bool IsShowZero(string strTemp){int len = strTemp.Length;var sub1 = strTemp.IndexOf("0");bool need0 = false;if (sub1 != -1){var less = strTemp.Length - sub1 - 1;if (len == 1 ||(less > 0 && strTemp.Substring(sub1 + 1).Count(p => p.Equals('0')) != less)){// 不是连续的0,要保留显示“零”need0 = true;}}return need0;}