最近项目需求,要求做语音播报。播报的部分 百度一大堆,我们采用多个语音文件合成+推送扩展的方式。这就涉及到把数字转换为白话文的功能。
比如:-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后直接拼就好
网友评论