You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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) // 输出: مائة دولار أمريكي و خمسون سنت لا غير

关键说明

  1. 语法规则适配:
    • 阿拉伯语数字存在阳性/阴性名词配合,转换时会根据大额单位的性别选择对应的数字词汇。
    • 11-19有独立词汇,无需拆分十位和个位;百位数字有特殊复数形式(如"مائتان"表示200)。
  2. 小数处理:
    • 默认将小数部分乘以100取整,对应货币的"分"单位,转换时使用阴性数字词汇(匹配"سنت"的阴性属性)。
  3. 货币整合:
    • 通过convertNumberWithCurrency方法直接传入主货币和小数货币名称,自动拼接成符合要求的完整表述。

内容的提问来源于stack exchange,提问作者user29056335

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 03:15:06