My第一个C#程序,中文字符与整数之间的互相转换
原创文章如转载请注明:转自¥忘%风 {http://www.cnblogs.com/slave_wc}
本文地址: My第一个C#程序,中文字符与整数之间的互相转换
测试情况:
1:输入异常判断:
2:简单数据测试
代码说明概要:
数字转中文基本思路:
即进行分解
1:计算最基本的[0,9999]的数字翻译
2:通过 '万' 字连接两个相邻的由(1)式计算所得的结果,得到[0,99999999]范围的翻译。
3:通过 '亿' 字连接,得到大数范围内的翻译。
中文转数字基本思路:
主要问题:1:在哪里进行乘法?2:乘法的作用范围呢?
容易进入的误区:
1:只考虑在哪里进行乘法,如一千万
(容易想到如,当计算到'万'字时,离它最近的单位为'千',这种情况下进行乘法,而除乘法外,则进行顺序计算)。
**测试数据:一亿三千万。由该算法得到表达式为:1e8 + 3000 * 10000。由于是顺序计算,实际计算时为 (1e8 + 3000) * 10000
得到了错误答案。
2:考虑到了(1)中遇到的问题,但对乘法作用范围判断出错。如数据一亿三千万,正确表达式为1e8 + (3000 * 10000)
误以为进行类似只有 '+' 与 '*' 的算式表达式的计算即可,即考虑了 '*' 与 '+' 的优先级。
如此如“一亿三千万”能得到正确答案了。
**测试数据:一亿零一百二十万。按(2)的算法,则为:1e 8 + 100 + (20 * 10000)。
而实际结果应为:1e8 + (100 + 20) * 10000,得到了错误答案。
总结出的解法:即考虑1:在哪里进行乘法?2:乘法的作用范围呢?
**如一亿零一百二十万。当遇到‘万’时,由前面的‘百’<‘万’决定了当前需要进行乘法。
**再由‘万’之前遇到的第一个 > ‘万’的单位(此处为亿),决定了 乘法的作用范围在两者之间。
得到该翻译的正确表达式:1e8 + (100 + 20) * 10000。
路过看到有异议欢迎来拍砖。
代码及必要注释如下:
private class num2Chinese { private static readonly string unit = "个十百千"; private static readonly string ala = "0123456789"; private static readonly string ch = "零一二三四五六七八九"; private static string transSmall(string num) {/*[0,一万)区间的翻译*/ string str = ""; string nn = num.TrimStart('0'); bool flag = false; int j = 0; for (int i = nn.Length - 1; i >= 0; i--, j++) { int no = ala.IndexOf(nn[i]); if (no != 0) flag = true; if (flag) { if (j != 0 && no != 0) str += unit[j]; if (!(no == 0 && str[str.Length - 1] == '零')) str += ch[no]; } } char[] s = str.ToCharArray(); Array.Reverse(s); str = new string(s); return str; } private static string trans(string num, int range, char ss) {/*递归求解。[0,千]通过'万'字可拼接成[0,千万],同理[0,千万]通过亿字连接。 参数含义: 将num字串按每range作为一组进行分解,并通过ss字符进行连接。(4位一组或八位一组)*/ string ret = ""; string input = num.TrimStart('0'); for (int i = input.Length - range; i > -range; i -= range) { int st = i, len = range;/*st与len分别表示每组串的起始位置及长度*/ if (i < 0) { st = 0; len = range + i; } string tmp = input.Substring(st, len); long nn = long.Parse(tmp); string cur = ""; if (nn == 0) { ret = ss + ret; continue; } if (ss == '万') { cur = transSmall(tmp) + ss; } else { cur = trans(tmp, 4, '万') + ss; }/*计算得到每组的值后,拼接ss字符到末尾*/ if (nn % 10 == 0 && ret.Length > 0 && ret[0] != '零') {/*当前组末尾有零时判断是否+零*/ int ll = num.Length - st - len; ll = ll > 8 ? 8 : ll;/ /*最大单位为亿,则当前组之后8位范围内无零则不输出零 例:一亿零五,零需要输出,一亿亿零五(而非一亿零亿零五)*/ string tt = num.Substring(st + len, ll); if (tt.Trim('0') != "")//后八位存在非0值 cur += '零'; } if (ss == '万' && nn < 1000 || ss == '亿' && nn < (long)1e7) {/*当前组前位空缺时,前位补零*/ cur = '零' + cur; } ret = cur + ret; } int s = 0, _len = ret.Length - 1; if (ret[0] == '零') { s = 1; _len--; } if (ret[ret.Length - 2] == '零') { _len--; }/*去掉多余的前位零和后位的ss单位符之后的子串*/ ret = ret.Substring(s, _len); return ret; } public static string transBigInteger(string ss) {/*调用trans进行翻译与异常处理,支持大数*/ string ret = ss.TrimStart('0'); string tt = "0123456789"; char[] ch = tt.ToCharArray(); ret = ret.Trim(' '); if (ret.Trim(ch) != "") { MessageBox.Show("输入数据非法!"); return ""; } if (ret == "") { return "零"; } ret = trans(ret, 8, '亿'); return ret; } } private class ChineseNumConvert {/*整数转数字类,不支持大数 关键点:在哪里进行乘法?计算乘法的范围?*/ private static readonly string Digit = "零一二三四五六七八九"; private static readonly string Unit = "个十百千万亿"; private static readonly int[] num = { 1, 10, 100, 1000, 10000, 100000000 }; private static bool checkString(string word) {/*简单判断输入是否合法 1;其他字符。 2:有非零数字相邻*/ word = word.Trim(' '); string tt = Digit + Unit; string tmp = word.Trim(tt.ToCharArray()); if (tmp != "") return false; for (int i = 0; i < word.Length - 1; i++) { if (Digit.IndexOf(word[i]) >= 1 && Digit.IndexOf(word[i + 1]) >= 1) { return false; } } return true; } public static long ChineseNum2Int(string word) { if (!checkString(word)) { MessageBox.Show("输入数据非法!"); return 0; } long sum = 0; long tmp = 0; long[] tt = new long[150]; int dig = -1, unit0 = -1, unit1 = -1, unit2 = -1; if (Unit.IndexOf(word[0]) >= 0) { word = "一" + word; } if (Unit.IndexOf(word[word.Length - 1]) < 0) { if (word.Length >= 2 && (tmp = Unit.IndexOf(word[word.Length - 2])) > 0) { word = word + Unit.ToCharArray()[tmp - 1]; } else { word += '个'; } } for (int i = 1; i < word.Length; i++) { dig = Digit.IndexOf(word[i - 1]); unit0 = Unit.IndexOf(word[i]); if (unit0 >= 0) { unit1 = -1; unit2 = -1; int idx = -1; for (int j = i - 1; j >= 0; j--) { unit1 = Unit.IndexOf(word[j]); if (unit1 >= 0) break; }//是否需要做乘法 for (int j = i - 1; j >= 0; j--) { unit2 = Unit.IndexOf(word[j]); if (unit2 > unit0) { idx = j; break; } }//决定乘法的作用范围 if (unit1 >= 0 && unit0 >= unit1) { if (dig >= 0) sum += dig; if (unit2 == -1) { sum *= num[unit0]; } else { sum = (sum - tt[idx]) * num[unit0] + tt[idx]; } } else { if (dig < 0) dig = 1; sum += dig * num[unit0]; } } tt[i] = sum; } return sum; }
}