iOS-数字转为人名币大写(Swift4.0)

在iOS中,对数字的格式化操作,我第一个想到的就是它NumberFormatter,所以我写了下面这个函数

extension String {
    func numberRMM() -> String {
        guard let num = Double(self) else {
            return ""
        }
        let format = NumberFormatter()
        format.locale = Locale(identifier: "zh_CN")
        format.numberStyle = .spellOut
        format.minimumIntegerDigits = 1
        format.minimumFractionDigits = 0
        format.maximumFractionDigits = 2
        return format.string(from: NSNumber(value: num)) ?? ""
    }
}

经测试后

// 输入
print(1234566.05.numberRMM())
// 打印结果 一百二十三万四千五百六十六点〇五

这显然不是我们要的结果,不过我们还是可以利用这个结果,再加上字符串替换,来实现我们的需求 首先全部字符串的替换如下函数

let formattedString = text.replacingOccurrences(of: "一", with: "壹")
                          .replacingOccurrences(of: "二", with: "贰")
                          .replacingOccurrences(of: "三", with: "叁")
                          .replacingOccurrences(of: "四", with: "肆")
                          .replacingOccurrences(of: "五", with: "伍")
                          .replacingOccurrences(of: "六", with: "陆")
                          .replacingOccurrences(of: "七", with: "柒")
                          .replacingOccurrences(of: "八", with: "捌")
                          .replacingOccurrences(of: "九", with: "玖")
                          .replacingOccurrences(of: "十", with: "拾")
                          .replacingOccurrences(of: "百", with: "佰")
                          .replacingOccurrences(of: "千", with: "仟")
                          .replacingOccurrences(of: "〇", with: "零")

之后我们再对这个字符串进行处理

  1. 先判断是否是整数,如果是整数,则在后面加上元整两个字就是我们要的结果了,代码如下 // 整数处理 let texts = formattedString.components(separatedBy: "点") if sept.count > 0 && isInt { return texts[0].appending("元整") }
  2. 如果是小数,此时无论有多少位小数,我们都需要保留两位小数,即角和分,后面的数字直接丢弃掉(实际业务中也不会出现有2位小数以上的数),处理方法如下 // 小数处理 let decStr = sept[1] intStr = intStr.appending("元").appending("\(decStr.first!)角") if decStr.count > 1 { intStr = intStr.appending("\(decStr[decStr.index(decStr.startIndex, offsetBy: 1)])分") } else { intStr = intStr.appending("零分") } return intStr

经过处理后再次测试如下

print(666.005.numberRMM()) // 陆佰陆拾陆元整
print(666.00.numberRMM())  // 陆佰陆拾陆元整
print(666.05.numberRMM())  // 陆佰陆拾陆元零角伍分
print(666.10.numberRMM())  // 陆佰陆拾陆元壹角零分
print(666.1.numberRMM())   // 陆佰陆拾陆元壹角零分
print(666.numberRMM())     // 陆佰陆拾陆元整

最后再贴一下完整的代码

extension Double {
    func numberRMM() -> String {
        return String(self).numberRMM()
    }
}
extension String {
    /// 人名币大写
    func numberRMM() -> String {
        guard let num = Double(self) else {
            return ""
        }
        let format = NumberFormatter()
        format.locale = Locale(identifier: "zh_CN")
        format.numberStyle = .spellOut
        format.minimumIntegerDigits = 1
        format.minimumFractionDigits = 0
        format.maximumFractionDigits = 2
        let text = format.string(from: NSNumber(value: num)) ?? ""
        let sept = self.components(separatedBy: ".")
        let decimals: Double? = sept.count == 2 ? Double("0." + sept.last!) : nil
        return self.formatRMM(text: text, isInt: decimals == nil || decimals! < 0.01)
    }

    private func formatRMM(text: String, isInt: Bool) -> String {
        let formattedString = text.replacingOccurrences(of: "一", with: "壹")
                                  .replacingOccurrences(of: "二", with: "贰")
                                  .replacingOccurrences(of: "三", with: "叁")
                                  .replacingOccurrences(of: "四", with: "肆")
                                  .replacingOccurrences(of: "五", with: "伍")
                                  .replacingOccurrences(of: "六", with: "陆")
                                  .replacingOccurrences(of: "七", with: "柒")
                                  .replacingOccurrences(of: "八", with: "捌")
                                  .replacingOccurrences(of: "九", with: "玖")
                                  .replacingOccurrences(of: "十", with: "拾")
                                  .replacingOccurrences(of: "百", with: "佰")
                                  .replacingOccurrences(of: "千", with: "仟")
                                  .replacingOccurrences(of: "〇", with: "零")
        let sept = formattedString.components(separatedBy: "点")
        var intStr = sept[0]
        if sept.count > 0 && isInt {
            // 整数处理
            return intStr.appending("元整")
        } else {
            // 小数处理
            let decStr = sept[1]
            intStr = intStr.appending("元").appending("\(decStr.first!)角")
            if decStr.count > 1 {
                intStr = intStr.appending("\(decStr[decStr.index(decStr.startIndex, offsetBy: 1)])分")
            } else {
                intStr = intStr.appending("零分")
            }
            return intStr
        }
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java达人

java反射简明示例

Java反射在我们Java学习的过程中是非常重要的知识点。可能有些同学认为这个学习起来不容易理解,其实就我个人而言还是比较简单,学习起来也比较容...

1756
来自专栏章鱼的慢慢技术路

LeetCode_1. Two Sum_Solution

这道题目的意思是给定一个数组和一个值,要求出这个数组中两个值的和等于这个给定值target。

1033
来自专栏Java学习123

Java反射(一)

2717
来自专栏java达人

java反射机制

基本概念   在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?   答案是肯定的。   这种...

18810
来自专栏java小白

反射调用方法,实例化对象,字段赋值

1553
来自专栏用户2442861的专栏

理解java Class类

http://blog.csdn.net/bingduanlbd/article/details/8424243/

411
来自专栏Java帮帮-微信公众号-技术文章全总结

【选择题】Java基础测试三(15道)

【选择题】Java基础测试三(15道) 26.关于以下程序代码的说明正确的是( D ) 1.class HasStatic{ 2. privat...

3577
来自专栏iOS开发攻城狮的集散地

assign,retain,copy,strong

1495
来自专栏技术墨客

JVM与字节码——2进制流字节码解析 原

本位将详细介绍字节码的2进制结构和JVM解析2进制流的规范。规范对字节码有非常严格的结构要求,其结构可以用一个JSON来描述:

552
来自专栏每日一篇技术文章

Swift3.0 - 文本输出

551

扫码关注云+社区