前言
最近遇到一个需求,需要把阿拉伯数字的金额如99.9元转换为中文数字金额玖拾玖元玖分。想了一下,感觉思绪有点混乱,就在网上找了下。方法有很多,择其一,根据自己的需求修改后,这里记录下来。大概思路如下:
1、声明需要用到的中文数字
// 汉字的数字
const cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
// 基本单位
const cnIntRadice = ['', '拾', '佰', '仟']
// 对应整数部分扩展单位
const cnIntUnits = ['', '万', '亿', '兆']
// 对应小数部分单位
const cnDecUnits = ['角', '分', '毫', '厘']
// 整数金额时后面跟的字符
const cnInteger = '整'
// 整型完以后的单位
const cnIntLast = '元'
2、定义两个变量分别存储整数部分和小数部分
// 金额整数部分
let IntegerNum
// 金额小数部分
let DecimalNum
if (money.indexOf('.') === -1) {
IntegerNum = money
DecimalNum = ''
} else {
const moneyArr = money.split('.')
IntegerNum = moneyArr[0]
DecimalNum = moneyArr[1].substr(0, 4)
}
3、将阿拉伯数字转为中文数字
这是整个流程的中心点和难点。大体的思路可分为:
- 0~9的阿拉伯数字转换,通过数字下标匹配获取
for (let i = 0; i < IntegerNum.length; i++) {
// 通过遍历拿到整数部分的每一项
let term = IntegerNum.substr(i, 1)
// 转换数字,cnNums是存储了中文零到玖的数组,直接将阿拉伯数字作为下标获取中文数字
ChineseStr += cnNums[parseInt(term)]
}
- 单位的获取
for (let i = 0; i < IntegerNum.length; i++) {
// 剩余待处理的数量
let surplus = IntLen - i - 1
// 用于获取整数部分的扩展单位
// 剩余数量除以4,比如12345,term为1时,expandUnit则为1,
// cnIntUnits[expandUnit]对应得到的单位为万
let expandUnit = surplus / 4
// 用于获取整数部分的基本单位
// 剩余数量取余4,比如123,那么第一遍遍历term为1,surplus为2,baseUnit则为2,
// 所以cnIntRadice[baseUnit]对应得到的基本单位为'佰'
let baseUnit = surplus % 4
// 基本单位转换之后直接加上
ChineseStr += cnNums[parseInt(term)] + cnIntRadice[baseUnit]
// 扩展单位要满足大单位进阶才加
// 同时满足以下两个条件则是大单位进阶
// 剩余数量是4的倍数,并且连续为0的数量不超过3个
if (baseUnit === 0 && zeroCount < 4) {
ChineseStr += cnIntUnits[expandUnit]
}
}
完整代码:
function changeNumberMoneyToChinese (money) {
// 接收数字或者字符串数字
if (typeof money === "string") {
if (money === '') return ''
if (isNaN(parseFloat(money))) {
throw Error(`参数有误:${money},请输入数字或字符串数字`)
} else {
// 去掉分隔符(,)
money = money.replace(/,/g, '')
}
} else if (typeof money === "number") {
// 去掉分隔符(,)
money = money.toString().replace(/,/g, '')
} else {
throw Error(`参数有误:${money},请输入数字或字符串数字`)
}
// 汉字的数字
const cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
// 基本单位
const cnIntRadice = ['', '拾', '佰', '仟']
// 对应整数部分扩展单位
const cnIntUnits = ['', '万', '亿', '兆']
// 对应小数部分单位
const cnDecUnits = ['角', '分', '毫', '厘']
// 整数金额时后面跟的字符
const cnInteger = '整'
// 整型完以后的单位
const cnIntLast = '元'
// 金额整数部分
let IntegerNum
// 金额小数部分
let DecimalNum
// 输出的中文金额字符串
let ChineseStr = ''
// 正负值标记
let Symbol = ''
// 转成浮点数
money = parseFloat(money)
// 如果是0直接返回结果
if (money === 0) {
ChineseStr = cnNums[0] + cnIntLast + cnInteger
return ChineseStr
}
// 如果小于0,则将Symbol标记为负,并转为正数
if (money < 0) {
money = -money
Symbol = '负 '
}
// 转换为字符串
money = money.toString()
// 将整数部分和小数部分分别存入IntegerNum和DecimalNum
if (money.indexOf('.') === -1) {
IntegerNum = money
DecimalNum = ''
} else {
const moneyArr = money.split('.')
IntegerNum = moneyArr[0]
DecimalNum = moneyArr[1].substr(0, 4)
}
// 获取整型部分转换
if (parseInt(IntegerNum, 10) > 0) {
let zeroCount = 0
let IntLen = IntegerNum.length
for (let i = 0; i < IntLen; i++) {
// 获取整数的每一项
let term = IntegerNum.substr(i, 1)
// 剩余待处理的数量
let surplus = IntLen - i - 1
// 用于获取整数部分的扩展单位
// 剩余数量除以4,比如12345,term为1时,expandUnit则为1,
// cnIntUnits[expandUnit]对应得到的单位为万
let expandUnit = surplus / 4
// 用于获取整数部分的基本单位
// 剩余数量取余4,比如123,那么第一遍遍历term为1,surplus为2,baseUnit则为2,
// 所以cnIntRadice[baseUnit]对应得到的基本单位为'佰'
let baseUnit = surplus % 4
if (term === '0') {
zeroCount++
} else {
// 连续存在多个0的时候需要补'零'
if (zeroCount > 0) {
ChineseStr += cnNums[0]
}
// 归零
zeroCount = 0
/*
cnNums是汉字的零到玖组成的数组,term则是阿拉伯0-9,
直接将阿拉伯数字作为下标获取中文数字
例如term是0则cnNums[parseInt(term)]取的就是'零',9取的就是'玖'
最后加上单位就转换成功了!
这里只加十百千的单位
*/
ChineseStr += cnNums[parseInt(term)] + cnIntRadice[baseUnit]
}
/*
如果baseUnit为0,意味着当前项和下一项隔了一个节权位即隔了一个逗号
扩展单位只有大单位进阶才需要,判断是否大单位进阶,则通过zeroCount判断
baseUnit === 0即存在逗号,baseUnit === 0 && zeroCount < 4 意为大单位进阶
*/
if (baseUnit === 0 && zeroCount < 4) {
ChineseStr += cnIntUnits[expandUnit]
}
}
ChineseStr += cnIntLast
}
// 小数部分转换
if (DecimalNum !== '') {
let decLen = DecimalNum.length
for (let i = 0; i < decLen; i++) {
// 同理,参考整数部分
let term = DecimalNum.substr(i, 1)
if (term !== '0') {
ChineseStr += cnNums[Number(term)] + cnDecUnits[i]
}
}
}
ChineseStr = Symbol + ChineseStr
return ChineseStr
}
最终结果:
阿拉伯数字金额转中文金额方法有很多种,至于这里为什么选择这一种,因为它跟我最初的想法有点相似,即通过数组匹配转换中文。
这里也感谢博主提供的思路,已点赞:)
THE END