美文网首页
【Swift】语音播报数字转汉字

【Swift】语音播报数字转汉字

作者: 十二生肖都背不全的家伙 | 来源:发表于2020-08-29 10:38 被阅读0次

    最近项目需求,要求做语音播报。播报的部分 百度一大堆,我们采用多个语音文件合成+推送扩展的方式。这就涉及到把数字转换为白话文的功能。
    比如:-987654300.210 转换成 负9亿8千7百6十5万4千3百点21元
    然后录制好每个字符串的语音文件,挨个拼接起来。
    实现代码放这里做个记录,顺便要是有类似需求的小伙伴,拿去用就好。这份代码目前支持到999999999999.99,应该够用了。

        
    func speakContent(_ price: Double) -> String {
        /// 是否为负数
        let isMinus = price < 0
        
        /// 正负单位
        let minusUnit = isMinus ? "负" : ""
        /// 单位
        let unit = "元"
        
        /// 绝对值
        let absPrice = fabs(price)
        /// 转字符串
        let numberStr = String.init(format: "%.2f", absPrice)
        /// 数字分割
        let cutResult = numberStr.components(separatedBy: ".")
        
        /// 整数部分
        let integralNum = Int(cutResult.first ?? "") ?? 0
        let integralPart = "\(integralNum)"
        
        /// 整数转换结果
        var integralResult = integralPart.enumerated().reduce("") { (accumulate, element) -> String in
            let (index, value) = element
            guard let num = Int(String(value)) else { return "" }
            if num == 0 {
                if accumulate.hasSuffix("0") {
                    return accumulate
                }else {
                    return accumulate + "0"
                }
            }else {
                let count = integralPart.count - 1 - index
                let unit = self.getUnit(index: count)
                return accumulate + String(value) + unit
            }
        }
        // 移除整数最后一位0
        integralResult.removeLastZero()
        
        /// 小数部分
        let fractionalPart = cutResult.count > 0 ? cutResult.last! : ""
        /// 小数转换结果
        var fractionalResult = fractionalPart.count > 0 ? "点\(fractionalPart)": ""
        // 移除小数最后一位0
        fractionalResult.removeLastZero()
        
        // 最终结果为 正负单位+整数部分+小数部分+单位
        return minusUnit + integralResult + fractionalResult + unit
    }
    
    /// 根据位数获取单位名称
    /// - Parameter index: 所在位数
    /// - Returns: 单位
    func getUnit(index: Int) -> String {
        var currentIndex: Int = 0
        if index > 4 && index % 4 > 0 {
            currentIndex = index % 4
        }else {
            currentIndex = index
        }
        switch currentIndex {
        case 1:
            return "十"
        case 2:
            return "百"
        case 3:
            return "千"
        case 4:
            return "万"
        case 8:
            return "亿"
        default:
            return ""
        }
    }
    
    // MARK: - Extensions
    // Extensions for String
    extension String {
        /// 移除最后一位0(只移除一个)
        mutating func removeLastZero() {
            if self.count > 1 && self.last == "0" {
                self = String(self[self.startIndex..<(self.index(self.endIndex, offsetBy: -1))])
            }
        }
    }
    

    大体的实现方式就是:
    结果由 正负、整数、小数、单位 四个部分组成
    正负很简单,判断小于0即可
    整数部分需要根据位数插入对应的单位,同时连续存在多个0的需要简化为一个,最后移除末尾的0。
    小数部分去除末尾0后直接拼就好

    相关文章

      网友评论

          本文标题:【Swift】语音播报数字转汉字

          本文链接:https://www.haomeiwen.com/subject/msvdsktx.html