分析
汉字用零一二三四五六七八九作为基数, 与阿拉伯数字靠数字偏移位置的权位不同, 中文数字是"数字+权位"的方式组成数字.
中文计数以万为小节, 万以下没有节权, 万之上是亿为节权(亿之上还有: 万亿, 兆, 万兆, 亿兆等)
/**
INT_MAX == 2147483647 (大概21.5亿)
// 数字转中文 - 算法分析
12 1234 1234
0. 以每四位为一小节进行分开
1. 将每小节的数字转为中文
> 从末端起, 循环遍历每一位
> 若不为0, 则拼接 数字 + 权位: 如 一 千 两 百 三 十 四
> 若为0, 则判断上一位是否为0, 若不为0, 拼接 "零", 否则, 拼接 ""
1001 => 一 千 零 一
2. 根据节权位进行拼接
十二 亿 一千两百三十四 万 一千两百三十四
// 中文转数字 - 算法分析 (逆向数字转中文)
0. 去掉中文中的"零", 在转数字的时候没用
1. 根据节权位"亿", "万"分开每一小节
2. 根据每一小节的中文转数字
> 一千两百三十四
> 依次遍历每个字符, 如果只是普通数字, 则保留, 如果是权位(千, 百, 十), 则将保留的数字 * 权位, 并相加, 1 * 1000 + 2 * 100 + 3 * 10
> 如果是小节的末位(个位), 直接相加.
3. 由每一小节部分的数字 * 节权值 得到最终的值
*/
直接上代码:
image.png
class LCExchange: NSObject {
// 数字转中文
static func number2Chinese(num: Int) -> String {
// 中文数字节权位
let chineseSectionPosition = ["", "万", "亿", "万亿"]
var numInt = num
if numInt == 0 {
return "零"
}
// 节权位标识
var sectionPosition = 0
// 输出的中文字符串
var endChineseNum = ""
// 每个小节转换的字符串
var sectionChineseNum = ""
// 将数字从右至左, 每隔4位, 分成一小节, 再分别对每小节处理
while numInt > 0 {
let section = numInt % 10000
sectionChineseNum = eachSection(num: section) //将当前小节转为中文
if section != 0 { // 当前小节不为0, 添加节权
sectionChineseNum += chineseSectionPosition[sectionPosition]
}
//去掉已经转换的末尾四位数
numInt = numInt / 10000
endChineseNum = sectionChineseNum + endChineseNum
sectionPosition += 1
}
if endChineseNum.mySubString(to: 1) == "零" {
endChineseNum = endChineseNum.mySubString(from: 1)
}
return endChineseNum
}
// 中文转数字
static func chinese2Number(chinese: String) -> Int {
var chineseNum = chinese
// 保存数字
var number = 0
// 保存亿节权部分, 第一四位
var yiStr = ""
// 保存万节权部分, 第二四位
var wanStr = ""
// 保存""节权部分, 第三四位
var kongStr = ""
// 记录节权位置
var k = 0
// 记录该节权部分是否被处理
var isDeal = true
// 去除字符串中的"零"
for (index,value) in chineseNum.enumerated() {
if value == "零" {
chineseNum = chineseNum.mySubString(to: index) + chineseNum.mySubString(from: index + 1)
}
}
// 各部分节权处理, 将中文以小节为单位截取存入不同的字符串中
for (index, value) in chineseNum.enumerated() {
if value == "亿" { // 截取亿的位置
yiStr = chineseNum.mySubString(to: index)
k = index + 1 // 亿后的一位
isDeal = false
}
if value == "万" {
// 截取 万 前面的字符
wanStr = chineseNum.mySubString(fromIndex: k, toIndex: index)
// 截取 万 后面的字符
kongStr = chineseNum.mySubString(from: index + 1)
isDeal = false
}
}
if isDeal { // 该数小于万
kongStr = chineseNum
}
// 将中文转换为数字
number = eachSection(chinese: yiStr) * 100000000 + eachSection(chinese: wanStr) * 10000 + eachSection(chinese: kongStr)
return number
}
}
extension LCExchange {
// 一个小节中, 数字转中文
private static func eachSection(num: Int) -> String {
var intNum = num
let chineseNumberArr = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
let chinesePositionArr = ["", "十", "百", "千"]
// 输出的小节中文
var chineseNum = ""
// 每小节内部只能有一个中文"零"
var isZero = false
for index in 0..<4 {
// 获取末尾值(取出个位)
let end = intNum % 10
// 判断该数字是否为0, 若不是0, 就直接拼接权位, 若是0, 则判断是否已经出现过中文"零"
if end == 0 {
if !isZero { // 上一位数不为0, 执行补0
isZero = true
chineseNum = chineseNumberArr[0] + chineseNum
}
}else {
isZero = false
chineseNum = chineseNumberArr[end] + chinesePositionArr[index] + chineseNum // 数字 + 权位
}
intNum = intNum / 10; // 去除原来的个位
}
return chineseNum
}
// 一个小节中, 中文转数字
private static func eachSection(chinese: String) -> Int {
var dataDic = [String: Int]()
let chineseArr = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
for (index, value) in chineseArr.enumerated() {
dataDic[value] = index
}
// 权位
dataDic["十"] = 10
dataDic["百"] = 100
dataDic["千"] = 1000
// 输出的数字
var resultInt = 0
// 每一个数字
var num = 0
for (index, char) in chinese.enumerated() {
let value = dataDic[String(char)] ?? 0
// 判断是否为权位
if value == 10 || value == 100 || value == 1000 {
resultInt += num * value
}else if index == chinese.count - 1 { // 判断是否为最后一位
resultInt += value
}else { // 不是个位
num = value
}
}
return resultInt
}
}
网友评论