维吾尔语数字读法转换器 - 设计与实现
完整代码在最下面封装到一个类里面大家随便用。

一、背景与需求
在维吾尔语语音合成(TTS)和文本处理场景中,经常需要将阿拉伯数字转换为维吾尔语的自然读法。例如:
123.45→بىر يۈز يىگىرمە ئۈچ پۈتۈن يۈزدىن قىرىق بەش100→يۈز(而非بىر يۈز)1000→مىڭ(而非بىر مىڭ)
这种转换需要遵循维吾尔语的数字读法习惯,包括数位规则、特殊省略规则、小数读法等。
二、维吾尔语数字读法规则
2.1 基础数字(0-9)
| 数字 | 维吾尔语 | 数字 | 维吾尔语 |
|---|---|---|---|
| 0 | نۆل | 5 | بەش |
| 1 | بىر | 6 | ئالتە |
| 2 | ئىككى | 7 | يەتتە |
| 3 | ئۈچ | 8 | سەككىز |
| 4 | تۆت | 9 | توققۇز |
2.2 十位整数的固定读法
维吾尔语中,整十数有固定的读法:
| 数字 | 维吾尔语 | 数字 | 维吾尔语 |
|---|---|---|---|
| 10 | ئون | 60 | ئاتمىش |
| 20 | يىگىرمە | 70 | يەتمىش |
| 30 | ئوتتۇز | 80 | سەكسەن |
| 40 | قىرىق | 90 | توقسان |
| 50 | ئەللىك |
2.3 数位单位
从右向左,每3位一组,对应的单位:
| 位置 | 单位 | 说明 |
|---|---|---|
| 第1组(个位组) | 无 | 0-999 |
| 第2组 | مىڭ | 千 |
| 第3组 | مىليۇن | 百万 |
| 第4组 | مىليارد | 十亿 |
| 第5组 | تىرىليۇn | 万亿 |
2.4 三位数读法规则
任意三位数(0-999)的读法:
- 百位 :数字 +
يۈز - 十位 :
- 整十:使用固定的整十读法
- 非整十:
十位词 + 个位数字
- 个位:直接读出数字
特殊规则: 当数字为 100 且是最高位组且后面没有非零组时,读作 يۈز,省略开头的 بىر。
2.5 分组读法示例
| 数字 | 分组 | 读法 |
|---|---|---|
| 223 | 223 | ئىككى يۈز يىگىرمە ئۈچ |
| 003 | 003 | ئۈچ |
| 223,003 | 223 | 003 | ئىككى يۈز يىگىرمە ئۈچ مىڭ ئۈچ |
2.6 小数读法
小数部分根据位数决定单位:
| 小数位数 | 单位 | 示例 |
|---|---|---|
| 1位 | ئوندىن | 0.5 → نۆل پۈتۈن ئوندىن بەش |
| 2位 | يۈزدىن | 12.43 → ئون ئىككى پۈتۈن يۈزدىن قىرىق ئۈچ |
| 3位 | مىڭدىن | 223003.234 → ئىككى يۈز يىگىرمە ئۈچ مىڭ ئۈچ پۈتۈن مىڭدىن ئىككى يۈز ئوتتۇز تۆت |
格式: 整数部分 + پۈتۈن + 小数单位 + 小数数字读法
2.7 特殊规则(省略"بىر")
当满足以下条件时,省略开头的 بىر:
- 数字以1开头
- 后面全是0
- 是最高位组且后面没有非零组
| 数字 | 常规读法 | 正确读法 | 说明 |
|---|---|---|---|
| 100 | بىر يۈز | يۈز | 100是整百 |
| 1000 | بىر مىڭ | مىڭ | 1000是整千 |
| 1000000 | بىر مىليۇن | مىليۇn | 100万是整百万 |
| 102 | بىر يۈز ئىككى | بىر يۈز ئىككى | 有零头,不省略 |
| 1001 | بىر مىڭ بىر | مىڭ بىر | 千位组后面有非零组 |
三、算法设计
3.1 核心流程
输入数字
↓
转为字符串
↓
处理科学计数法
↓
处理负数
↓
分离整数和小数
↓
整数部分处理 ← 从右向左每3位分组 → 每组独立读 → 加单位
↓
小数部分处理 ← 判断位数 → 加单位 → 读取数字
↓
拼接:整数部分 + پۈتۈن + 小数部分
↓
处理负数符号
↓
返回结果
3.2 整数部分处理算法
function readIntegerPart(numStr):
去除前导零
如果 numStr == "0": 返回 "نۆل"
// 从右向左每3位分组
groups = []
while numStr 还有字符:
groups.push(numStr.slice(-3))
numStr = numStr.slice(0, -3)
groups.reverse()
result = []
for group in groups:
if group == 0: continue
// 判断是否为最高位组
isFirst = (index == 0)
// 检查后面是否有非零组
hasFollowingNonZero = check(groups, index)
// 读取当前组(三位数)
words = readThreeDigits(group, isFirst, hasFollowingNonZero)
result.push(words)
// 添加单位
unitIndex = groups.length - 1 - index
if unitIndex > 0:
result.push(UNITS[unitIndex])
return result
3.3 三位数读法算法
function readThreeDigits(num, isFirst, hasFollowingNonZero):
if num == 0: return []
result = []
hundreds = floor(num / 100)
remainder = num % 100
// 处理百位
if hundreds > 0:
// 特殊规则:100 读作 "يۈز"
if hundreds == 1 && remainder == 0 && isFirst && !hasFollowingNonZero:
result.push("يۈز")
else:
result.push(DIGITS[hundreds])
result.push("يۈز")
// 处理十位和个位
if remainder > 0:
if remainder < 10:
result.push(DIGITS[remainder])
else if remainder % 10 == 0:
result.push(TENS[remainder])
else:
tens = floor(remainder / 10) * 10
ones = remainder % 10
result.push(TENS[tens])
result.push(DIGITS[ones])
return result
3.4 小数部分处理算法
function readDecimalPart(decimalStr):
if decimalStr为空: return []
len = decimalStr.length
unit = DECIMAL_UNITS[len]
// 超过3位小数,逐位读出
if unit不存在:
逐位读取每个数字
return result
// 去除前导零后读取
num = parseInt(decimalStr)
if num == 0:
return [unit, "نۆل"]
// 按三位一组读取
result = readIntegerPart(String(num))
result.unshift(unit) // 添加小数单位
return result
四、实现方案
4.1 技术选型
- 语言:JavaScript(ES6+)
- 运行环境:浏览器
- 设计模式:类封装
- 字符集:UTF-8(支持维吾尔语阿拉伯字母)
4.2 类结构设计
javascript
class UyghurNumberConverter {
// 静态数据映射
static DIGITS = { ... } // 0-9基础数字
static TENS = { ... } // 10-90整十数
static UNITS = [ ... ] // 数位单位
static DECIMAL_UNITS = { ... } // 小数单位
// 核心方法
static readThreeDigits() // 读取三位数
static hasNonZeroAfter() // 检查后续非零组
static readIntegerPart() // 读取整数部分
static readDecimalPart() // 读取小数部分
// 公开API
convert() // 单个转换
convertBatch() // 批量转换
convertWithFormat() // 格式化输出
}
4.3 数据映射
基础数字:
javascript
DIGITS = {
0: 'نۆل', 1: 'بىر', 2: 'ئىككى', 3: 'ئۈچ',
4: 'تۆت', 5: 'بەش', 6: 'ئالتە',
7: 'يەتتە', 8: 'سەككىز', 9: 'توققۇز'
}
整十数:
javascript
TENS = {
10: 'ئون', 20: 'يىگىرمە', 30: 'ئوتتۇز',
40: 'قىرىق', 50: 'ئەللىك', 60: 'ئاتمىش',
70: 'يەتمىش', 80: 'سەكسەن', 90: 'توقسان'
}
数位单位:
javascript
UNITS = ['', 'مىڭ', 'مىليۇن', 'مىليارد', 'تىرىليۇn']
小数单位:
javascript
DECIMAL_UNITS = {
1: 'ئوندىن', // 十分位
2: 'يۈزدىن', // 百分位
3: 'مىڭدىن' // 千分位
}
五、使用示例
5.1 基础使用
javascript
// 创建转换器实例
const converter = new UyghurNumberConverter();
// 转换整数
converter.convert(123); // "بىر يۈز يىگىرمە ئۈچ"
converter.convert(100); // "يۈز"
converter.convert(1000); // "مىڭ"
converter.convert(1001); // "مىڭ بىر"
// 转换小数
converter.convert(12.43); // "ئون ئىككى پۈتۈن يۈزدىن قىرىق ئۈچ"
converter.convert(100.6); // "يۈز پۈتۈن ئوندىن ئالتە"
converter.convert(223003.234); // "ئىككى يۈز يىگىرمە ئۈچ مىڭ ئۈچ پۈتۈن مىڭدىن ئىككى يۈز ئوتتۇز تۆت"
5.2 批量转换
javascript
const numbers = [1, 10, 100, 1000];
converter.convertBatch(numbers);
// ['بىر', 'ئون', 'يۈز', 'مىڭ']
5.3 格式化输出
javascript
const result = converter.convertWithFormat(12345.67);
// {
// number: 12345.67,
// reading: 'ئون ئىككى مىڭ ئۈچ يۈز قىرىق بەش پۈتۈن يۈزدىن ئاتمىش يەتتە',
// formatted: '12,345.67'
// }
六、测试用例
6.1 测试数据
javascript
const testCases = [
0, 5, 12, 20, 43, 99,
100, 102, 130, 200, 305,
1000, 1001, 1100, 12345,
223003, 1000000, 1000001, 1000100,
12.43, 100.6, 1000.5, 223003.234,
3.14, 0.5, 100.01,
1234567890, -123, -3.14
];
6.2 预期输出
| 数字 | 维吾尔语读法 |
|---|---|
| 0 | نۆل |
| 100 | يۈز |
| 102 | بىر يۈز ئىككى |
| 1000 | مىڭ |
| 1001 | مىڭ بىر |
| 223003.234 | ئىككى يۈز يىگىرمە ئۈچ مىڭ ئۈچ پۈتۈن مىڭدىن ئىككى يۈز ئوتتۇز تۆت |
七、性能与优化
7.1 时间复杂度
- 单次转换:O(log n),其中n为数字大小
- 批量转换:O(k log n),k为数字个数
7.2 空间复杂度
- 转换过程中使用数组存储中间结果
- 内存占用与数字位数成正比
7.3 优化点
- 缓存机制:对重复出现的数字可考虑缓存结果
- 流式处理:对于超大数字,可考虑流式处理避免内存溢出
- 预编译:将静态数据预编译,减少运行时开销
八、扩展性考虑
8.1 支持更多数位
当前支持到 تىرىليۇn(万亿),如需支持更大数字,只需扩展 UNITS 数组。
8.2 支持更多小数位
当前支持3位小数(千分位),如需支持更多位,可扩展 DECIMAL_UNITS 或实现逐位读法。
8.3 支持其他语言
该设计模式可推广到其他语言的数字读法转换,只需替换数据映射和读法规则。
九、总结
本文介绍了维吾尔语数字读法转换器的设计与实现,包括:
- 完整的规则整理:基础数字、整十数、数位单位、分组读法、小数读法、特殊规则
- 清晰的算法设计:核心流程、整数处理、小数处理、三位数读法
- 完善的实现方案:类封装、数据映射、API设计
- 丰富的使用示例:单个转换、批量转换、格式化输出
该工具可广泛应用于维吾尔语TTS配音、文本处理、教育软件等场景,具有良好的实用价值和扩展性。