如何在Swift中实现阿拉伯语数字转单词(含货币与小数)
问题:Swift实现阿拉伯语数字转单词(含货币支持)
我想要开发一款Swift应用,实现阿拉伯语的数字转单词功能,参考类似tafqeet.com的效果,支持添加货币名称。例如:100.5应转换为阿拉伯语表述“مائة دولار أمريكي و خمسون سنت لا غير”(对应英文含义“One hundred US Dollars and Fifty Cents”)。
我已掌握英文数字转单词的实现方式,代码如下:
func numberToWords(_ num: Int) -> String { let units = ["", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"] let teens = ["", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"] let tens = ["", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"] let thousands = ["", "Thousand", "Million", "Billion"] if num == 0 { return "Zero" } var num = num var result = "" var thousandCounter = 0 while num > 0 { if num % 1000 != 0 { result = helper(num % 1000) + thousands[thousandCounter] + " " + result } num /= 1000 thousandCounter += 1 } return result.trimmingCharacters(in: .whitespaces) } private func helper(_ num: Int) -> String { let units = ["", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"] let teens = ["", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"] let tens = ["", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"] if num == 0 { return "" } if num < 10 { return units[num] + " " } if num < 20 { return teens[num - 10] + " " } if num < 100 { return tens[num / 10] + " " + helper(num % 10) } return units[num / 100] + " Hundred " + helper(num % 100) }
该代码在英文场景下运行良好,但阿拉伯语数字有更复杂的语法规则与格式。我了解NSNumberFormatter工具,但它不直接支持阿拉伯语数字转单词功能。
需要实现的功能要求:
- 符合阿拉伯语数字的语法规则;
- 支持105.75这类小数数字。
解决方案
阿拉伯语数字转单词需要遵循其独特的语法规则,比如名词的性配合、特殊数字(如11-19)的独立表述、大额单位的分级,以及小数部分的处理逻辑。以下是完整的Swift实现:
核心实现代码
import Foundation struct ArabicNumberToWords { // 基础数字词汇(阳性/阴性区分) private let unitsMasculine = ["", "واحد", "اثنان", "ثلاثة", "أربعة", "خمسة", "ستة", "سبعة", "ثمانية", "تسعة"] private let unitsFeminine = ["", "واحدة", "اثنتان", "ثلاث", "أربع", "خمس", "ست", "سبع", "ثمان", "تسع"] private let teens = ["", "أحد عشر", "اثنا عشر", "ثلاثة عشر", "أربعة عشر", "خمسة عشر", "ستة عشر", "سبعة عشر", "ثمانية عشر", "تسعة عشر"] private let tens = ["", "عشرة", "عشرون", "ثلاثون", "أربعون", "خمسون", "ستون", "سبعون", "ثمانون", "تسعون"] private let hundreds = ["", "مائة", "مائتان", "ثلاثمائة", "أربعمائة", "خمسمائة", "ستمائة", "سبعمائة", "ثمانمائة", "تسعمائة"] // 大额单位(标注性别:false=阳性,true=阴性) private let largeUnits = [ (name: "", gender: false), (name: "ألف", gender: false), (name: "مليون", gender: true), (name: "مليار", gender: false) ] /// 转换整数部分为阿拉伯语单词 private func convertIntegerPart(_ num: Int, isFeminineContext: Bool = false) -> String { guard num != 0 else { return "صفر" } var num = num var result = "" var unitIndex = 0 while num > 0 { let chunk = num % 1000 if chunk != 0 { let chunkWords = convertThreeDigitChunk(chunk, isFeminine: largeUnits[unitIndex].gender) let unitName = largeUnits[unitIndex].name let chunkWithUnit = unitName.isEmpty ? chunkWords : "\(chunkWords) \(unitName)" result = result.isEmpty ? chunkWithUnit : "\(chunkWithUnit) و \(result)" } num /= 1000 unitIndex += 1 } return result.trimmingCharacters(in: .whitespaces) } /// 处理三位数字块 private func convertThreeDigitChunk(_ num: Int, isFeminine: Bool) -> String { var parts = [String]() // 处理百位 let hundred = num / 100 if hundred > 0 { parts.append(hundreds[hundred]) } let remainder = num % 100 // 处理十位和个位 if remainder > 0 { if remainder < 10 { let unit = isFeminine ? unitsFeminine[remainder] : unitsMasculine[remainder] parts.append(unit) } else if remainder < 20 { parts.append(teens[remainder - 10]) } else { let ten = remainder / 10 let unit = remainder % 10 var tenPart = tens[ten] if unit > 0 { let unitWord = isFeminine ? unitsFeminine[unit] : unitsMasculine[unit] tenPart = "\(unitWord) و \(tenPart)" } parts.append(tenPart) } } return parts.joined(separator: " و ") } /// 转换小数部分为阿拉伯语单词(默认保留两位小数,对应货币分) private func convertFractionalPart(_ num: Int) -> String { guard num != 0 else { return "" } return convertIntegerPart(num, isFeminineContext: true) } /// 完整转换数字(含小数)并添加货币名称 func convertNumberWithCurrency(_ number: Double, mainCurrency: String, fractionalCurrency: String) -> String { let integerPart = Int(number) let fractionalPart = Int(round((number - Double(integerPart)) * 100)) var parts = [String]() // 处理整数部分 let integerWords = convertIntegerPart(integerPart) parts.append("\(integerWords) \(mainCurrency)") // 处理小数部分 if fractionalPart > 0 { let fractionalWords = convertFractionalPart(fractionalPart) parts.append("\(fractionalWords) \(fractionalCurrency)") } // 添加结尾的"لا غير"(可根据需求移除) let result = parts.joined(separator: " و ") return "\(result) لا غير" } } // 使用示例 let converter = ArabicNumberToWords() let result = converter.convertNumberWithCurrency(100.5, mainCurrency: "دولار أمريكي", fractionalCurrency: "سنت") print(result) // 输出: مائة دولار أمريكي و خمسون سنت لا غير
关键说明
- 语法规则适配:
- 阿拉伯语数字存在阳性/阴性名词配合,转换时会根据大额单位的性别选择对应的数字词汇。
- 11-19有独立词汇,无需拆分十位和个位;百位数字有特殊复数形式(如"مائتان"表示200)。
- 小数处理:
- 默认将小数部分乘以100取整,对应货币的"分"单位,转换时使用阴性数字词汇(匹配"سنت"的阴性属性)。
- 货币整合:
- 通过
convertNumberWithCurrency方法直接传入主货币和小数货币名称,自动拼接成符合要求的完整表述。
- 通过
内容的提问来源于stack exchange,提问作者user29056335
相关产品推荐
相关产品推荐

