如何在数字转英文单词算法中适配11-19的特殊数字处理
数字转英文单词算法:修复11-19数值处理问题
现有数字转英文单词的算法能正常处理除11-19之外的数字,但无法处理出现在数字首尾或中间的11-19这类数值,需在现有算法框架内解决该问题。
原实现代码:
int i = 0, multiplier = 1, length = nums.Length - 1; string[] lessThanTwentyWords = new string[] { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" }; string[] tens = new string[] { "Ten", "Twenty", "Thirty", "Fourty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" }; Dictionary<int, KeyValuePair<string, string[]>> posVsWordsMap = new Dictionary<int, KeyValuePair<string, string[]>>() { [1] = new KeyValuePair<string, string[]>("", lessThanTwentyWords), [10] = new KeyValuePair<string, string[]>("", tens), [100] = new KeyValuePair<string, string[]>("Hundred", lessThanTwentyWords), [1000] = new KeyValuePair<string, string[]>("Thousand", lessThanTwentyWords), [10000] = new KeyValuePair<string, string[]>("", tens), [100000] = new KeyValuePair<string, string[]>("Hundred", lessThanTwentyWords), [1000000] = new KeyValuePair<string, string[]>("Million", lessThanTwentyWords), // 可继续补全更高位映射 }; string completeText = ""; for (var i = nums.Length - 1; i >= 0; i--) { var number = nums[i]; if (number != 0) { string text = posVsWordsMap[multiplier].Value[number - 1]; var hundredsText = posVsWordsMap[multiplier].Key; multiplier *= 10; completeText += text + hundredsText; } }
问题根源
原算法采用逐位单独处理逻辑,但11-19是两位一体的特殊数值,逐位拆分后会生成错误拼接结果(比如11会被拆成十位1和个位1,得到TenOne而非Eleven);同时存在拼写错误(Fourty应为Forty),且字符串拼接顺序是低位到高位,最终结果反向。
修复方案(基于现有框架调整)
- 增加特殊两位数判断:迭代处理十位级数位(乘数为10、10000等)时,优先检查当前位与下一位组成的数是否在11-19范围内,若是则直接取对应单词并跳过下一位迭代。
- 修正拼写与补全字典:修正
tens数组的拼写错误,补全高位映射项。 - 调整拼接顺序:用列表收集结果片段,最后反转得到正确的高位到低位顺序。
修改后的完整代码
string NumberToWords(int number) { if (number == 0) return "Zero"; string[] lessThanTwentyWords = new string[] { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" }; string[] tens = new string[] { "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" }; // 数位映射:键为10的幂次,值为(数位后缀,对应单词数组) Dictionary<int, (string Suffix, string[] Words)> posVsWordsMap = new Dictionary<int, (string, string[])>() { [1] = ("", lessThanTwentyWords), [10] = ("", tens), [100] = ("Hundred", lessThanTwentyWords), [1000] = ("Thousand", lessThanTwentyWords), [10000] = ("", tens), [100000] = ("Hundred", lessThanTwentyWords), [1000000] = ("Million", lessThanTwentyWords), [10000000] = ("", tens), [100000000] = ("Hundred", lessThanTwentyWords) }; List<string> parts = new List<string>(); int remaining = number; int multiplier = 1; while (remaining > 0) { int digit = remaining % 10; remaining /= 10; if (digit == 0) { multiplier *= 10; continue; } // 处理十位级数位,检查是否组成11-19 if (multiplier == 10 || multiplier == 10000 || multiplier == 10000000) { int twoDigit = digit * 10 + (remaining % 10); if (twoDigit >= 11 && twoDigit <= 19) { parts.Add(lessThanTwentyWords[twoDigit - 1]); remaining /= 10; multiplier *= 10; } else { parts.Add(tens[digit - 1] + posVsWordsMap[multiplier].Suffix); } } else { // 处理个位、百位等非十位级别 parts.Add(posVsWordsMap[multiplier].Words[digit - 1] + posVsWordsMap[multiplier].Suffix); } multiplier *= 10; } parts.Reverse(); return string.Join(" ", parts); }
关键改动说明
- 用
List<string>收集结果片段,最后反转得到正确的高位到低位顺序,解决原代码拼接反向问题。 - 在十位级数位处理中增加两位数判断,命中11-19范围时直接取对应单词并跳过下一位。
- 修正
tens数组拼写错误,用元组简化字典定义,提升可读性。 - 增加0的特殊处理,符合数字转英文的常规逻辑。
内容的提问来源于stack exchange,提问作者Usman
相关产品推荐
相关产品推荐

